CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
-PROJECT(certsvc C)
+PROJECT(certsvc)
-SET(PREFIX ${CMAKE_INSTALL_PREFIX})
-SET(EXEC_PREFIX "\${prefix}")
-SET(LIBDIR "\${prefix}/lib")
-SET(INCLUDEDIR "\${prefix}/include")
-SET(VERSION_MAJOR 1)
-SET(VERSION "${VERSION_MAJOR}.0.0")
+INCLUDE(FindPkgConfig)
-INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
+SET(SO_VERSION 1)
+SET(VERSION "${SO_VERSION}.0.0")
-INCLUDE(FindPkgConfig)
-pkg_check_modules(pkgs REQUIRED openssl dlog)
+# define debug output
+SET(DEBUG_OUTPUT "-DCERT_SVC_LOG") # for debug
+#SET(DEBUG_OUTPUT "-DCERT_SVC_LOG_CONSOLE") # for debug
-FOREACH(flag ${pkgs_CFLAGS})
-SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
-ENDFOREACH(flag)
+SET(TARGET_CERT_SVC_LIB "cert-svc")
+SET(TARGET_VCORE_LIB "cert-svc-vcore")
+SET(TARGET_SIGN_TOOL "dpkg-pki-sig")
-SET(source_dir "./srcs")
-SET(include_dir "./include")
+# compiler options
+SET(CMAKE_C_FLAGS_RELEASE "-fvisibility=hidden -Wall -O2")
+SET(CMAKE_CXX_FLAGS_RELEASE "-std=c++0x -Wall -O2")
-# About debug
-SET(debug "-DCERT_SVC_LOG") # for debug
-#SET(debug "-DCERT_SVC_LOG_CONSOLE") # for debug
+SET(CMAKE_C_FLAGS_DEBUG "-fvisibility=hidden -Wall -O0 -g")
+SET(CMAKE_CXX_FLAGS_DEBUG "-std=c++0x -Wall -O0 -g")
-SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
-SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+SET(CMAKE_C_FLAGS_CCOV "-fvisibility=hidden -Wall -O2 --coverage")
+SET(CMAKE_CXX_FLAGS_CCOV "-std=c++0x -Wall -O2 --coverage")
-###################################################################################################
+SET(CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed")
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed")
+SET(CMAKE_SKIP_RPATH "TRUE")
+
+################################################################################
# for libcert-svc.so
-SET(libcert-svc_SOURCES
- ${source_dir}/cert-service.c
- ${source_dir}/cert-service-util.c
- ${source_dir}/cert-service-store.c
- ${source_dir}/cert-service-process.c )
-SET(libcert-svc_LDFLAGS " -module -avoid-version ${pkgs_LDFALGS} ")
-SET(libcert-svc_CFLAGS " ${CFLAGS} -fvisibility=hidden -g -fPIC -I${CMAKE_CURRENT_SOURCE_DIR}/include ${debug} ")
-SET(libcert-svc_CPPFLAGS " -DPIC ")
-
-ADD_LIBRARY(cert-svc SHARED ${libcert-svc_SOURCES})
-TARGET_LINK_LIBRARIES(cert-svc ${pkgs_LDFLAGS} -L${prefix}/lib -lpthread)
-SET_TARGET_PROPERTIES(cert-svc PROPERTIES COMPILE_FLAGS "${libcert-svc_CFLAGS} ${libcert-svc_CPPFLAGS}")
-SET_TARGET_PROPERTIES(cert-svc PROPERTIES SOVERSION ${VERSION_MAJOR})
-SET_TARGET_PROPERTIES(cert-svc PROPERTIES VERSION ${VERSION})
-###################################################################################################
-
-###################################################################################################
+################################################################################
+
+PKG_CHECK_MODULES(CERT_SVC_DEPS
+ openssl
+ dlog
+ glib-2.0
+ REQUIRED
+)
+
+SET(CERT_SVC_SOURCES
+ ${PROJECT_SOURCE_DIR}/srcs/cert-service.c
+ ${PROJECT_SOURCE_DIR}/srcs/cert-service-util.c
+ ${PROJECT_SOURCE_DIR}/srcs/cert-service-store.c
+ ${PROJECT_SOURCE_DIR}/srcs/cert-service-process.c
+)
+
+IF(DEFINED DEBUG_OUTPUT)
+ SET_SOURCE_FILES_PROPERTIES(${CERT_SVC_SOURCES}
+ PROPERTIES COMPILE_FLAGS ${DEBUG_OUTPUT})
+ENDIF(DEFINED DEBUG_OUTPUT)
+
+INCLUDE_DIRECTORIES(
+ ${PROJECT_SOURCE_DIR}/include
+ ${CERT_SVC_DEPS_INCLUDE_DIRS}
+)
+
+ADD_LIBRARY(${TARGET_CERT_SVC_LIB} SHARED ${CERT_SVC_SOURCES})
+
+SET_TARGET_PROPERTIES(${TARGET_CERT_SVC_LIB} PROPERTIES
+ SOVERSION ${SO_VERSION}
+ VERSION ${VERSION}
+)
+
+TARGET_LINK_LIBRARIES(${TARGET_CERT_SVC_LIB}
+ pthread
+ ${CERT_SVC_DEPS_LIBRARIES}
+)
+
+################################################################################
# for dpkg-pki-sig
-SET(PackageSignVerify_SOURCES
- ${source_dir}/dpkg-pki-sig.c
- ${source_dir}/cert-service-util.c )
-SET(PackageSignVerify_CFLAGS " -fvisibility=hidden -I. -I${CMAKE_CURRENT_SOURCE_DIR}/include ${debug} ")
-SET(PackageSignVerify_LDFALGS " -module -avoid-version ${pkgs_LDFLAGS} ")
+################################################################################
+
+SET(SIGN_TOOL_SOURCES
+ ${PROJECT_SOURCE_DIR}/srcs/dpkg-pki-sig.c
+ ${PROJECT_SOURCE_DIR}/srcs/cert-service-process.c
+ ${PROJECT_SOURCE_DIR}/srcs/cert-service-util.c
+)
-ADD_EXECUTABLE(dpkg-pki-sig ${PackageSignVerify_SOURCES})
-TARGET_LINK_LIBRARIES(dpkg-pki-sig ${pkgs_LDFLAGS} cert-svc)
-SET_TARGET_PROPERTIES(dpkg-pki-sig PROPERTIES COMPILE_FLAGS "${PackageSignVerify_CFLAGS} ")
-###################################################################################################
+ADD_EXECUTABLE(${TARGET_SIGN_TOOL} ${SIGN_TOOL_SOURCES})
+
+TARGET_LINK_LIBRARIES(${TARGET_SIGN_TOOL}
+ ${TARGET_CERT_SVC_LIB}
+ ${CERT_SVC_DEPS_LIBRARIES}
+)
+
+################################################################################
CONFIGURE_FILE(cert-svc.pc.in cert-svc.pc @ONLY)
+CONFIGURE_FILE(cert-svc-vcore.pc.in cert-svc-vcore.pc @ONLY)
+
+INSTALL(TARGETS ${TARGET_CERT_SVC_LIB} DESTINATION ${LIBDIR} COMPONENT RuntimeLibraries)
+INSTALL(PROGRAMS ${TARGET_SIGN_TOOL} DESTINATION ${BINDIR})
+INSTALL(FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/cert-svc.pc
+ ${CMAKE_CURRENT_BINARY_DIR}/cert-svc-vcore.pc
+ DESTINATION ${LIBDIR}/pkgconfig
+)
+INSTALL(FILES ${PROJECT_SOURCE_DIR}/targetinfo DESTINATION /opt/share/cert-svc/)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/cert-service.h DESTINATION ${INCLUDEDIR})
+
+# Now we must create empty directory for certificates.
+# Without this directories rpm package will fail during build.
+INSTALL(DIRECTORY ${PROJECT_SOURCE_DIR}/etc/empty
+ DESTINATION /usr/share/cert-svc/ca-certs/code-signing/native
+ FILES_MATCHING PATTERN THISPATTERNMUSTNOTMATCH
+)
+INSTALL(DIRECTORY ${PROJECT_SOURCE_DIR}/etc/empty
+ DESTINATION /usr/share/cert-svc/ca-certs/code-signing/wac
+ FILES_MATCHING PATTERN THISPATTERNMUSTNOTMATCH
+)
+INSTALL(DIRECTORY ${PROJECT_SOURCE_DIR}/etc/empty
+ DESTINATION /opt/share/cert-svc/certs/code-signing/wac
+ FILES_MATCHING PATTERN THISPATTERNMUSTNOTMATCH
+)
+INSTALL(DIRECTORY ${PROJECT_SOURCE_DIR}/etc/empty
+ DESTINATION /opt/share/cert-svc/certs/sim/operator
+ FILES_MATCHING PATTERN THISPATTERNMUSTNOTMATCH
+)
+INSTALL(DIRECTORY ${PROJECT_SOURCE_DIR}/etc/empty
+ DESTINATION /opt/share/cert-svc/certs/sim/thirdparty
+ FILES_MATCHING PATTERN THISPATTERNMUSTNOTMATCH
+)
+INSTALL(DIRECTORY ${PROJECT_SOURCE_DIR}/etc/empty
+ DESTINATION /opt/share/cert-svc/certs/user
+ FILES_MATCHING PATTERN THISPATTERNMUSTNOTMATCH
+)
+INSTALL(DIRECTORY ${PROJECT_SOURCE_DIR}/etc/empty
+ DESTINATION /opt/share/cert-svc/certs/trusteduser
+ FILES_MATCHING PATTERN THISPATTERNMUSTNOTMATCH
+)
+INSTALL(DIRECTORY ${PROJECT_SOURCE_DIR}/etc/empty
+ DESTINATION /opt/share/cert-svc/certs/mdm/security
+ FILES_MATCHING PATTERN THISPATTERNMUSTNOTMATCH
+)
+INSTALL(DIRECTORY ${PROJECT_SOURCE_DIR}/etc/empty
+ DESTINATION /opt/share/cert-svc/certs/mdm/security/cert
+ FILES_MATCHING PATTERN THISPATTERNMUSTNOTMATCH
+)
+INSTALL(DIRECTORY ${PROJECT_SOURCE_DIR}/etc/empty
+ DESTINATION /opt/share/cert-svc/pkcs12
+ FILES_MATCHING PATTERN THISPATTERNMUSTNOTMATCH
+)
-INSTALL(TARGETS cert-svc DESTINATION lib COMPONENT RuntimeLibraries)
-INSTALL(PROGRAMS ${CMAKE_BINARY_DIR}/dpkg-pki-sig DESTINATION bin)
-INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/cert-svc.pc DESTINATION lib/pkgconfig)
-INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/targetinfo DESTINATION /opt/share/cert-svc/)
-INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/cert-service.h DESTINATION include)
+ADD_SUBDIRECTORY(vcore)
+ADD_SUBDIRECTORY(etc)
--- /dev/null
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ 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.
+
--- /dev/null
+Copyright (c) Samsung Electronics Co., Ltd. All rights reserved.
+Except as noted, this software is licensed under Apache License, Version 2.
+Please, see the LICENSE.APLv2 file for Apache License terms and conditions.
--- /dev/null
+prefix=@PREFIX@
+exec_prefix=@EXEC_PREFIX@
+libdir=@LIBDIR@
+includedir=@INCLUDEDIR@/cert-svc
+
+Name: cert-svc-vcore
+Description: cert-svc-vcore
+Version: @VERSION@
+Requires: cert-svc libxml-2.0 libxslt openssl libsoup-2.4 dpl-efl secure-storage xmlsec1
+Libs: -lcert-svc-vcore -L${libdir}
+Cflags: -I${includedir}
+
-cert-svc (1.0.1-17) unstable; urgency=low
+cert-svc (1.0.1-38) unstable; urgency=low
- * add certificate store for MDM
- * Git: pkgs/c/cert-svc
- * Tag: cert-svc_1.0.1-17
+ * Removed unused certificate files.
+ * Removed unused fingerprint_list files.
+ * Added Tizenmember domain.
+ * Refactored build script for cert-svc lib.
- -- Kidong Kim <kd0228.kim@samsung.com> Thu, 02 Feb 2012 09:29:17 +0900
+ * Git : framework/security/cert-svc
-cert-svc (1.0.1-16) unstable; urgency=low
+ -- Bartlomiej Grzelewski <b.grzelewski@samsung.com> Thu, 25 Oct 2012 11:12:00 +0100
- * 11/12/21
- * - remove self-signed certificate from certificate chain
- * Git: pkgs/c/cert-svc
- * Tag: cert-svc_1.0.1-16
+cert-svc (1.0.1-37) unstable; urgency=low
- -- Kidong Kim <kd0228.kim@samsung.com> Wed, 21 Dec 2011 10:06:41 +0900
+ * Fixed crash with adding pfx certificates to Microsoft Exchange account
+ * Fixed crash when cyclic directory structure detected
+ * License file copied to /usr/share/license/
+ * Added CryptoHash module to cert-svc-vcore
+ * Fixed CMakeLists.txt for proper permissions to SO file cert-svc-vcore
-cert-svc (1.0.1-15) unstable; urgency=low
+ * Git : framework/security/cert-svc
- * 11/12/07
- * - add boiler-plate on testcases
- * Git: pkgs/c/cert-svc
- * Tag: cert-svc_1.0.1-15
+ -- Tomasz Swierczek <t.swierczek@samsung.com> Fri, 19 Oct 2012 16:19:00 +0100
- -- Kidong Kim <kd0228.kim@samsung.com> Wed, 07 Dec 2011 09:47:17 +0900
+cert-svc (1.0.1-36) unstable; urgency=low
+
+ * Added access to Email Address field in certificate
+ * Added tests for access to private keys for two distinct processes
+ * Added manifest for "define" section only
+ * Refactored vcore headers/api
+ * Changed location of symbolic link to openssl certificates
+
+ * Git : framework/security/cert-svc
+ * Tag : cert-svc_1.0.1-36
+
+ -- Tomasz Swierczek <t.swierczek@samsung.com> Fri, 05 Oct 2012 17:03:00 +0100
+
+cert-svc (1.0.1-35) unstable; urgency=low
+
+ * Merged pkcs#12 tests cases made by Bartlomiej Grzelewski and Jacek Migacz. Some test cases were duplicated.
+ * Added creation of empty pkcs12 subfolder.
+
+ * Git : framework/security/cert-svc
+ * Tag : cert-svc_1.0.1-35
+
+ -- Tomasz Swierczek <t.swierczek@samsung.com> Fri, 21 Sep 2012 12:13:00 +0200
+
+cert-svc (1.0.1-34) unstable; urgency=low
+
+ * Fixed loading container with intermediate certificates.
+
+ * Git : framework/security/cert-svc
+ * Tag : cert-svc_1.0.1-34
+
+ -- Tomasz Swierczek <t.swierczek@samsung.com> Mon, 10 Sep 2012 14:15:00 +0200
+
+cert-svc (1.0.1-33) unstable; urgency=low
+
+ * Fixed issue while reading private key from PFX container
+ * Fixed segmentation fault while fetching certificates list from container w/o certificates
+
+ * Git : framework/security/cert-svc
+ * Tag : cert-svc_1.0.1-33
+
+ -- Tomasz Swierczek <t.swierczek@samsung.com> Mon, 03 Sep 2012 14:22:00 +0200
+
+cert-svc (1.0.1-31) unstable; urgency=low
+
+ * Add dependencies to xmlsec1 and libxml-2.0.
+
+ * Git : framework/security/cert-svc
+ * Tag : cert-svc_1.0.1-31
+
+ -- Bartlomiej Grzelewski <b.grzelewski@samsung.com> Thu, 17 Aug 2012 10:45:00 +0200
+
+cert-svc (1.0.1-30) unstable; urgency=low
+
+ * Remove UI from cert-svc repository.
+
+ * Git : slp/pkgs/c/cert-svc
+ * Tag : cert-svc_1.0.1-30
+
+ -- Bartlomiej Grzelewski <b.grzelewski@samsung.com> Thu, 16 Aug 2012 16:25:00 +0200
+
+cert-svc (1.0.1-29) unstable; urgency=low
+
+ * Fixed cert-svc-vcore pc file
+
+ * Git : slp/pkgs/c/cert-svc
+ * Tag : cert-svc_1.0.1-29
+
+ -- Tomasz Swierczek <t.swierczek@samsung.com> Tue, 14 Aug 2012 10:12:00 +0200
+
+
+cert-svc (1.0.1-28) unstable; urgency=low
+
+ * Remove "com.samsung" from source
+ * Add an "delete pkcs12/pfx" funcionality and screen to Cert UI
+ * Switch dependencies from ui-gadget to ui-gadget-1
+ * Link ubuntu certificates into cert-svc store.
+ * Fix api.
+
+ * Git : framework/security/cert-svc
+ * Tag : cert-svc_1.0.1-28
+
+ -- Tomasz Swierczek <t.swierczek@samsung.com> Mon, 13 Aug 2012 18:51:00 +0200
--- /dev/null
+mgr-app (0.0.1-1) unstable; urgency=low
+
+ * first source package for building
+
+ -- ManHyun Hwang <mh222.hwang@samsung.com> Thu, 30 JUN 2011 13:43:34 +0900
+
--- /dev/null
+libug-setting-manage-application-efl (0.0.1-1) unstable; urgency=low
+
+ * first source package for building
+
+ -- ManHyun Hwang <mh222.hwang@samsung.com> Thu, 30 JUN 2011 13:43:34 +0900
+
--- /dev/null
+Name=manage application
+Exec=${PREFIX}/bin/mgr-app
+Hidden=False
+Version=@VERSION@
+Type=Application
+X-TIZEN-TaskManage=True
+X-TIZEN-Multiple=False
+
+Name[en_US]=manage application
+Name[nl_NL]=manage application
+Name[de_DE]=manage application
+Name[zh_HK]=manage application
+Name[zh_CN]=manage application
+Name[ru_RU]=manage application
+Name[ko_KR]=manage application
+Name[zh_TW]=manage application
+Name[ja_JP]=manage application
+Name[es_ES]=manage application
+Name[el_GR]=manage application
+Name[it_IT]=manage application
+Name[tr_TR]=manage application
+Name[pt_PT]=manage application
+Name[fr_FR]=manage application
+
--- /dev/null
+#!/bin/sh
+
+# file owner
+if [ ${USER} == "root" ]
+then
+ echo "Test if"
+else
+ eche "Test else"
+fi
+
Section: libs
Priority: extra
Maintainer: KiDong Kim <kd0228.kim@samsung.com>
-Uploaders:
-Build-Depends: libssl-dev, dlog-dev, ca-certificates
-Standards-Version: 1.0.0
-Homepage: N/A
+Build-Depends: debhelper (>= 5),
+ libappcore-efl-dev,
+ autotools-dev,
+ libelm-dev,
+ libslp-setting-dev,
+ libui-gadget-dev,
+ libbundle-dev,
+ libaul-1-dev,
+ libefreet-dev,
+ libeina-dev,
+ shared-mime-info,
+# java-runtime-dev,
+ libail-0-dev,
+ libpkgmgr-client-dev,
+ libjava-parser-dev,
+ debhelper (>= 7.0.50),
+ libssl-dev,
+ dlog-dev,
+ ca-certificates,
+ wrt-commons-dev,
+ libxmlsec1-dev,
+ libsoup2.4-dev,
+ libecore-dev,
+ libxml2-dev,
+ libpcre-dev,
+ libslp-tapi-dev,
+ libappsvc-dev
-Package: libcert-svc-dev
+Package: libcert-svc1-ui
Section: libs
Architecture: any
-Depends: ${misc:Depends}, libcert-svc-0 (= ${Source-Version}), libssl-dev, dlog-dev
+Depends: ${shlibs:Depends}, ${misc:Depends}, libappsvc-dev
+Description: Manage Application package
+
+#Package: libug-setting-manage-application-efl-dbg
+#Section: debug
+#Architecture: any
+#Depends: ${shlibs:Depends}, ${misc:Depends}, libug-setting-manage-application-efl-0 (= ${binary:Version})
+#Description: Manage Application debug(unstripped) package
+
+Package: libcert-svc-dev
+Section: libdevel
+Architecture: any
+Depends: ${misc:Depends}, libcert-svc1 (= ${binary:Version}), libssl-dev, dlog-dev
Description: Certification service development package
-Package: libcert-svc-0
+Package: libcert-svc1
Section: libs
Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}
+Provides: libcert-svc-0
+Replaces: libcert-svc-0
+Depends: ${shlibs:Depends}, ${misc:Depends}, sqlite3
Description: Certification service library and executable
-Package: libcert-svc-dbg
+Package: libcert-svc1-dbg
Section: debug
Architecture: any
-Depends: ${misc:Depends}, libcert-svc-0
+Provides: libcert-svc-dbg
+Replaces: libcert-svc-dbg
+Depends: ${misc:Depends}, libcert-svc1 (= ${binary:Version})
Description: debug package of cert-svc library
+
+Package: libcert-svc1-test
+Section: libs
+Architecture: any
+Depends: ${misc:Depends}, ${shlibs:Depends}, libcert-svc1 (= ${binary:Version})
+Description: test program for cert-svc
--- /dev/null
+Source: mgr-app
+Section: libs
+Priority: extra
+Maintainer: SangJun Na <juni.na@samsung.com>, Manhyun Hwang <mh222.hwang@samsung.com>, Eunmi Son <eunmi.son@samsung.com>
+Build-Depends: debhelper (>= 5),
+ libappcore-efl-dev,
+ autotools-dev,
+ libelm-dev,
+ libslp-setting-dev,
+ libui-gadget-dev,
+ libbundle-dev,
+ libaul-1-dev,
+ libefreet-dev,
+ libeina-dev,
+ shared-mime-info,
+# java-runtime-dev,
+ libail-0-dev,
+ libpkgmgr-client-dev,
+ libjava-parser-dev
+
+Package: mgr-app-0
+Section: libs
+Architecture: armel
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: Manage Application package
+
+Package: mgr-app-dbg
+Section: debug
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, mgr-app-0 (= ${binary:Version})
+Description: Manage Application debug(unstripped) package
--- /dev/null
+Source: libug-setting-manage-application-efl
+Section: libs
+Priority: extra
+Maintainer: SangJun Na <juni.na@samsung.com>, Manhyun Hwang <mh222.hwang@samsung.com>, Eunmi Son <eunmi.son@samsung.com>
+Build-Depends: debhelper (>= 5),
+ libappcore-efl-dev,
+ autotools-dev,
+ libelm-dev,
+ libslp-setting-dev,
+ libui-gadget-dev,
+ libbundle-dev,
+ libaul-1-dev,
+ libefreet-dev,
+ libeina-dev,
+ shared-mime-info,
+# java-runtime-dev,
+ libail-0-dev,
+ libpkgmgr-client-dev,
+ libjava-parser-dev
+
+Package: libug-setting-manage-application-efl-0
+Section: libs
+Architecture: armel
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: Manage Application package
+
+Package: libug-setting-manage-application-efl-dbg
+Section: debug
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, libug-setting-manage-application-efl-0 (= ${binary:Version})
+Description: Manage Application debug(unstripped) package
--- /dev/null
+/usr/include/*
+/usr/lib/pkgconfig/*
+/usr/lib/*.so
--- /dev/null
+/usr/bin/cert-svc-test*
+/opt/apps/widget/tests/vcore_widget_uncompressed/*
+/opt/apps/widget/tests/vcore_keys/*
+/opt/apps/widget/tests/vcore_certs/*
+/opt/apps/widget/tests/pkcs12/*
+/opt/share/cert-svc/certs/code-signing/wac/root_cacert0.pem
--- /dev/null
+/opt/ug/lib/libmgr-cert-common.so
+/opt/ug/lib/libmgr-cert-view.so
+/opt/ug/lib/libug-setting-manage-certificates-efl.so.*
+/opt/ug/lib/libug-setting-manage-certificates-efl.so
+/opt/ug/res/edje/ug-setting-manage-certificates-efl/
+/opt/ug/res/images/ug-setting-manage-certificates-efl/
+/opt/ug/res/locale/*/*/ug-setting-manage-certificates-efl.mo
--- /dev/null
+/usr/share/cert-svc/ca-certs/code-signing/java/operator
+/usr/share/cert-svc/ca-certs/code-signing/java/manufacture
+/usr/share/cert-svc/ca-certs/code-signing/java/thirdparty
+/usr/share/cert-svc/ca-certs/code-signing/debian
+/usr/share/cert-svc/ca-certs/code-signing/wac
+/opt/share/cert-svc/certs/code-signing/java/operator
+/opt/share/cert-svc/certs/code-signing/java/manufacture
+/opt/share/cert-svc/certs/code-signing/java/thirdparty
+/opt/share/cert-svc/certs/code-signing/wac
+/opt/share/cert-svc/certs/sim/operator
+/opt/share/cert-svc/certs/sim/thirdparty
+/opt/share/cert-svc/certs/ssl
+/opt/share/cert-svc/certs/user
+/opt/share/cert-svc/certs/trusteduser
+/opt/share/cert-svc/certs/mdm/security/cert
--- /dev/null
+/usr/bin/cert_svc_create_clean_db.sh
+/usr/lib/*.so.*
+/usr/bin/dpkg-pki-sig
+/opt/share/cert-svc/targetinfo
+/usr/share/cert-svc/cert_svc_vcore_db.sql
+/usr/share/cert-svc/fingerprint_list.xml
+/usr/share/cert-svc/fingerprint_list.xsd
+/usr/share/cert-svc/schema.xsd
+/opt/share/cert-svc/certs/code-signing/wac/wac0.root.preproduction.pem
+/opt/share/cert-svc/certs/code-signing/wac/wac0.root.production.pem
+/opt/share/cert-svc/certs/code-signing/wac/wac0.publisherid.pem
+/opt/share/cert-svc/certs/code-signing/wac/tizen0.root.preproduction.cert.pem
+
--- /dev/null
+/opt/etc/ssl/certs/ /usr/share/cert-svc/ca-certs/ssl
--- /dev/null
+#!/bin/sh -e
+
+USE_CERT=6524
+
+case "$1" in
+ configure)
+ if [ `whoami` = "root" ]
+ then
+ chown -R root:${USE_CERT} /opt/share/cert-svc/certs/
+ chmod -R 0775 /opt/share/cert-svc/certs/
+ fi
+
+ if [ -z ${2} ]
+ then
+ echo "This is new install of wrt-security"
+ echo "Calling /usr/bin/cert_svc_create_clean_db.sh"
+ /usr/bin/cert_svc_create_clean_db.sh
+ else
+ # Find out old and new version of databases
+ VCORE_OLD_DB_VERSION=`sqlite3 /opt/dbspace/.cert_svc_vcore.db ".tables" | grep "DB_VERSION_"`
+ VCORE_NEW_DB_VERSION=`cat /usr/share/cert-svc/cert_svc_vcore_db.sql | tr '[:blank:]' '\n' | grep DB_VERSION_`
+ echo "OLD vcore database version ${VCORE_OLD_DB_VERSION}"
+ echo "NEW vcore database version ${VCORE_NEW_DB_VERSION}"
+
+ if [ ${VCORE_OLD_DB_VERSION} -a ${VCORE_NEW_DB_VERSION} ]
+ then
+ if [ ${VCORE_OLD_DB_VERSION} = ${VCORE_NEW_DB_VERSION} ]
+ then
+ echo "Equal database detected so db installation ignored"
+ else
+ echo "Calling /usr/bin/cert_svc_create_clean_db.sh"
+ /usr/bin/cert_svc_create_clean_db.sh
+ fi
+ else
+ echo "Calling /usr/bin/cert_svc_create_clean_db.sh"
+ /usr/bin/cert_svc_create_clean_db.sh
+ fi
+ fi
+ ;;
+
+ abort-upgrade|abort-remove|abort-deconfigure)
+ ;;
+
+ *)
+ echo "postinst called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
+ppTYPE ?= ugapp
+
CFLAGS ?= -Wall -g
-CXXFLAGS ?= -Wall -g
-LDFLAGS ?=
-PREFIX ?= /usr
-DATADIR ?= /opt
+LDFLAGS ?=
+ifneq (,$(findstring app,$(TYPE)))
+ PKGNAME ?= mgr-app
+ PREFIX ?= /opt/apps/mgr-app
+ RESDIR ?= /opt/apps/mgr-app/res
+ DATADIR ?= /opt/apps/mgr-app/data
+else
+ PKGNAME ?= libug-setting-manage-certificates-efl
+ PREFIX ?= /opt/ug
+ RESDIR ?= /opt/ug/res
+ DATADIR ?= /opt/ug/res/etc
+endif
ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
- CFLAGS += -O0
- CXXFLAGS += -O0
+ CFLAGS += -O0
+ BUILD_TYPE=Debug
else
- CFLAGS += -O2
- CXXFLAGS += -O2
+ CFLAGS += -O2
+ BUILD_TYPE=Release
endif
LDFLAGS += -Wl,--rpath=$(PREFIX)/lib -Wl,--as-needed
+CMAKE_BUILD_DIR ?= $(CURDIR)/cmake_build_tmp
+CMAKE_CERT_SVC_BUILD_DIR ?= $(CURDIR)/library
+
+
configure: configure-stamp
configure-stamp:
dh_testdir
# Add here commands to configure the package.
- CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" cmake . -DCMAKE_INSTALL_PREFIX=$(PREFIX)
-
- touch configure-stamp
+ cd $(CMAKE_CERT_SVC_BUILD_DIR) && cmake .
+ mkdir -p $(CMAKE_BUILD_DIR) && cd $(CMAKE_BUILD_DIR) && CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" cmake ../ui/ -DCMAKE_INSTALL_PREFIX="$(PREFIX)" -DCMAKE_BUILD_TYPE="$(BUILD_TYPE)" -DPKGNAME="$(PKGNAME)" -DTYPE="$(TYPE)"
+ touch $(CMAKE_BUILD_DIR)/configure-stamp
+ touch $(CMAKE_CERT_SVC_BUILD_DIR)/configure-stamp
build: build-stamp
-
-build-stamp: configure-stamp
+build-stamp: configure-stamp
dh_testdir
# Add here commands to compile the package.
- $(MAKE)
- #docbook-to-man debian/wavplayer.sgml > wavplayer.1
-
- for f in `find $(CURDIR)/debian/ -name "*.in"`; do \
+ cd $(CMAKE_CERT_SVC_BUILD_DIR) && $(MAKE)
+ cd $(CMAKE_BUILD_DIR) && $(MAKE)
+
+ for f in `find $(CURDIR)/debian/ -name "$(PREFIX)*.in"`; do \
cat $$f > $${f%.in}; \
sed -i -e "s#@PREFIX@#$(PREFIX)#g" $${f%.in}; \
+ sed -i -e "s#@RESDIR@#$(RESDIR)#g" $${f%.in}; \
sed -i -e "s#@DATADIR@#$(DATADIR)#g" $${f%.in}; \
+ sed -i -e "s#@PKGNAME@#$(PKGNAME)#g" $${f%.in}; \
done
-
- touch $@
+ touch $(CMAKE_BUILD_DIR)/$@
+ touch $(CMAKE_CERT_SVC_BUILD_DIR)/$@
clean:
dh_testdir
dh_testroot
rm -f build-stamp configure-stamp
- # Add here commands to clean up after the build process.
- -$(MAKE) clean
- rm -rf CMakeCache.txt
- rm -rf CMakeFiles
- rm -rf cmake_install.cmake
- rm -rf Makefile
- rm -rf install_manifest.txt
- rm -rf *.so
- rm -rf *.pc
- rm -rf *.service
+ # Add here commands to clean up after the build process.
+ rm -rf $(CMAKE_BUILD_DIR)
for f in `find $(CURDIR)/debian/ -name "*.in"`; do \
rm -f $${f%.in}; \
done
-
dh_clean
install: build
dh_clean -k
dh_installdirs
- # Add here commands to install the package into debian/wavplayer.
- $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install
+ cd $(CMAKE_BUILD_DIR) && $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install
+ cd $(CMAKE_CERT_SVC_BUILD_DIR) && $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install
# Build architecture-independent files here.
binary-arch: build install
dh_testdir
dh_testroot
- dh_installchangelogs
- dh_installdocs
- dh_installexamples
+ #dh_installchangelogs
+ #dh_installdocs
+ #dh_installexamples
dh_install --sourcedir=debian/tmp
-# dh_installmenu
-# dh_installdebconf
-# dh_installlogrotate
-# dh_installemacsen
-# dh_installpam
-# dh_installmime
-# dh_python
-# dh_installinit
-# dh_installcron
-# dh_installinfo
+ #dh_installmenu
+ #dh_installdebconf
+ #dh_installlogrotate
+ #dh_installemacsen
+ #dh_installpam
+ #dh_installmime
+ #dh_python
+ #dh_installinit
+ #dh_installcron
+ #dh_installinfo
dh_installman
dh_link
- dh_strip --dbg-package=libcert-svc-dbg
+ #dh_strip --dbg-package=$(PKGNAME)-dbg
dh_compress
dh_fixperms
-# dh_perl
+ #dh_perl
dh_makeshlibs
dh_installdeb
dh_shlibdeps
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install configure
+
--- /dev/null
+SET(ETC_DIR ${PROJECT_SOURCE_DIR}/etc)
+
+INSTALL(FILES
+ ${ETC_DIR}/cert_svc_create_clean_db.sh
+ DESTINATION /usr/bin
+ )
--- /dev/null
+#!/bin/sh
+# 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.
+#
+for name in cert_svc_vcore
+do
+ rm -f /opt/dbspace/.$name.db
+ rm -f /opt/dbspace/.$name.db-journal
+ SQL="PRAGMA journal_mode = PERSIST;"
+ sqlite3 /opt/dbspace/.$name.db "$SQL"
+ SQL=".read /usr/share/cert-svc/"$name"_db.sql"
+ sqlite3 /opt/dbspace/.$name.db "$SQL"
+ touch /opt/dbspace/.$name.db-journal
+ chown root:6026 /opt/dbspace/.$name.db
+ chown root:6026 /opt/dbspace/.$name.db-journal
+ chmod 660 /opt/dbspace/.$name.db
+ chmod 660 /opt/dbspace/.$name.db-journal
+done
+
+
/* Variable definitions */
/*********************************************************************************/
+struct cert_svc_inode_set;
+
/*********************************************************************************/
/* Variable definitions */
/*********************************************************************************/
int parse_name_fld_data(unsigned char* str, cert_svc_name_fld_data* fld);
int parse_time_fld_data(unsigned char* before, unsigned char* after, cert_svc_validity_fld_data* fld);
int search_data_field(search_field fldName, char* fldData, cert_svc_cert_descriptor* certDesc);
-int get_filelist_recur(char* dirName, cert_svc_filename_list* fileNames, int* fileNum);
-int get_all_certificates(cert_svc_filename_list* allCerts);
+int get_filelist_recur(char* dirName, cert_svc_filename_list* fileNames,
+ struct cert_svc_inode_set *visited);
+int get_all_certificates(cert_svc_filename_list** allCerts);
int sort_cert_chain(cert_svc_linked_list** unsorted, cert_svc_linked_list** sorted);
cert_svc_linked_list* find_issuer_from_list(cert_svc_linked_list* list, cert_svc_linked_list* p);
/*
* certification service
*
- * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
* Contact: Kidong Kim <kd0228.kim@samsung.com>
*
#define CERT_SVC_ERR_PERMISSION_DENIED -16
#define CERT_SVC_ERR_IS_EXPIRED -17
/* default certificate file path */
-#define CERT_SVC_STORE_PATH "/opt/share/cert-svc/certs/"
-#define CERT_SVC_STORE_PATH_DEFAULT "/opt/share/cert-svc/certs/ssl/"
-#define CERT_SVC_SEARCH_PATH_RO "/usr/share/cert-svc/ca-certs/"
-#define CERT_SVC_SEARCH_PATH_RW "/opt/share/cert-svc/certs/"
+#define CERT_SVC_STORE_PATH "/opt/share/cert-svc/certs/"
+#define CERT_SVC_STORE_PATH_DEFAULT "/opt/share/cert-svc/certs/ssl/"
+#define CERT_SVC_SEARCH_PATH_RO "/usr/share/cert-svc/ca-certs/"
+#define CERT_SVC_SEARCH_PATH_RW "/opt/share/cert-svc/certs/"
/*********************************************************************************/
/* Type definitions */
--- /dev/null
+<manifest>
+ <define>
+ <domain name="cert-svc" />
+ <provide>
+ <label name="cert-svc::private-key" />
+ <label name="cert-svc::certs-sharing" />
+ <label name="cert-svc::db" />
+ </provide>
+ </define>
+ <request>
+ <domain name="_" />
+ </request>
+</manifest>
-Name: cert-svc
-Summary: Certification service
-Version: 1.0.1
-Release: 0
-Group: System/Libraries
-License: Apache2.0
-Source0: cert-svc-%{version}.tar.gz
-Requires(post): /sbin/ldconfig
+#sbs-git:slp/pkgs/c/cert-svc cert-svc 1.0.1 ad7eb7efcefb37b06017c69cb2fc44e6f7b6cab7
+Name: cert-svc
+Summary: Certification service
+Version: 1.0.1
+Release: 45
+Group: System/Libraries
+License: SAMSUNG
+Source0: %{name}-%{version}.tar.gz
+Source1: %{name}.manifest
+
+Requires(post): /sbin/ldconfig
Requires(postun): /sbin/ldconfig
BuildRequires: cmake
-
-BuildRequires: pkgconfig(dnet)
BuildRequires: pkgconfig(dlog)
BuildRequires: pkgconfig(openssl)
-
+BuildRequires: pkgconfig(evas)
+BuildRequires: pkgconfig(dpl-efl)
+BuildRequires: pkgconfig(libsoup-2.4)
+BuildRequires: pkgconfig(libpcre)
+BuildRequires: pkgconfig(libpcrecpp)
+BuildRequires: pkgconfig(xmlsec1)
+BuildRequires: pkgconfig(secure-storage)
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(libxml-2.0)
+BuildRequires: pkgconfig(libxslt)
+
+Provides: libcert-svc-vcore.so.1
%description
-Certification service
+Certification service
%package devel
-Summary: Download agent
+Summary: Certification service (development files)
Group: Development/Libraries
Requires: %{name} = %{version}-%{release}
%description devel
-Certification service (developement files)
+Certification service (developement files)
%prep
%setup -q
-
%build
-cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix}
-
-
+%{!?build_type:%define build_type "Release"}
+cmake . -DPREFIX=%{_prefix} \
+ -DEXEC_PREFIX=%{_exec_prefix} \
+ -DLIBDIR=%{_libdir} \
+ -DBINDIR=%{_bindir} \
+ -DINCLUDEDIR=%{_includedir} \
+ -DCMAKE_BUILD_TYPE=%{build_type}
make %{?jobs:-j%jobs}
%install
rm -rf %{buildroot}
+mkdir -p %{buildroot}/usr/share/license
+cp LICENSE.APLv2 %{buildroot}/usr/share/license/%{name}
%make_install
+install -D %{SOURCE1} %{buildroot}%{_datadir}/%{name}.manifest
+ln -sf /opt/etc/ssl/certs %{buildroot}/opt/share/cert-svc/certs/ssl
+touch %{buildroot}/opt/share/cert-svc/pkcs12/storage
+chmod 766 %{buildroot}/opt/share/cert-svc/pkcs12/storage
+%clean
+rm -rf %{buildroot}
-%post -p /sbin/ldconfig
-
-%postun -p /sbin/ldconfig
-
+%post
+/sbin/ldconfig
+if [ -z ${2} ]; then
+ echo "This is new install of wrt-security"
+ echo "Calling /usr/bin/cert_svc_create_clean_db.sh"
+ /usr/bin/cert_svc_create_clean_db.sh
+else
+ # Find out old and new version of databases
+ VCORE_OLD_DB_VERSION=`sqlite3 /opt/dbspace/.cert_svc_vcore.db ".tables" | grep "DB_VERSION_"`
+ VCORE_NEW_DB_VERSION=`cat /usr/share/cert-svc/cert_svc_vcore_db.sql | tr '[:blank:]' '\n' | grep DB_VERSION_`
+ echo "OLD vcore database version ${VCORE_OLD_DB_VERSION}"
+ echo "NEW vcore database version ${VCORE_NEW_DB_VERSION}"
+
+ if [ ${VCORE_OLD_DB_VERSION} -a ${VCORE_NEW_DB_VERSION} ]; then
+ if [ ${VCORE_OLD_DB_VERSION} = ${VCORE_NEW_DB_VERSION} ]; then
+ echo "Equal database detected so db installation ignored"
+ else
+ echo "Calling /usr/bin/cert_svc_create_clean_db.sh"
+ /usr/bin/cert_svc_create_clean_db.sh
+ fi
+ else
+ echo "Calling /usr/bin/cert_svc_create_clean_db.sh"
+ /usr/bin/cert_svc_create_clean_db.sh
+ fi
+fi
+
+%postun
+/sbin/ldconfig
%files
%defattr(-,root,root,-)
-/usr/bin/dpkg-pki-sig
+%manifest %{_datadir}/%{name}.manifest
+%attr(0755,root,root) %{_bindir}/cert_svc_create_clean_db.sh
+%{_libdir}/*.so.*
+%{_bindir}/dpkg-pki-sig
/opt/share/cert-svc/targetinfo
-/usr/lib/libcert-svc.so.1
-/usr/lib/libcert-svc.so.1.0.0
+%{_datadir}/cert-svc/cert_svc_vcore_db.sql
+%{_datadir}/license/%{name}
+%dir %attr(0755,root,use_cert) /usr/share/cert-svc
+%dir %attr(0755,root,use_cert) /usr/share/cert-svc/ca-certs
+%dir %attr(0755,root,use_cert) /usr/share/cert-svc/ca-certs/code-signing
+%dir %attr(0755,root,use_cert) /usr/share/cert-svc/ca-certs/code-signing/native
+%dir %attr(0755,root,use_cert) /usr/share/cert-svc/ca-certs/code-signing/wac
+%dir %attr(0775,root,use_cert) /opt/share/cert-svc
+%dir %attr(0775,root,use_cert) /opt/share/cert-svc/certs
+%dir %attr(0775,root,use_cert) /opt/share/cert-svc/certs/code-signing
+%dir %attr(0775,root,use_cert) /opt/share/cert-svc/certs/code-signing/wac
+%dir %attr(0775,root,use_cert) /opt/share/cert-svc/certs/sim
+%dir %attr(0775,root,use_cert) /opt/share/cert-svc/certs/sim/operator
+%dir %attr(0775,root,use_cert) /opt/share/cert-svc/certs/sim/thirdparty
+%dir %attr(0777,root,use_cert) /opt/share/cert-svc/certs/user
+%dir %attr(0777,root,use_cert) /opt/share/cert-svc/certs/trusteduser
+%dir %attr(0775,root,use_cert) /opt/share/cert-svc/certs/mdm
+%dir %attr(0775,root,use_cert) /opt/share/cert-svc/certs/mdm/security
+%dir %attr(0775,root,use_cert) /opt/share/cert-svc/certs/mdm/security/cert
+%dir %attr(0777,root,use_cert) /opt/share/cert-svc/pkcs12
+/opt/share/cert-svc/certs/ssl
+/opt/share/cert-svc/pkcs12/storage
%files devel
%defattr(-,root,root,-)
-/usr/lib/pkgconfig/cert-svc.pc
-/usr/lib/libcert-svc.so
-/usr/include/cert-service.h
-
-
+%{_includedir}/*
+%{_libdir}/pkgconfig/*
+%{_libdir}/*.so
/*
* certification service
*
- * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
* Contact: Kidong Kim <kd0228.kim@samsung.com>
*
#include <dirent.h>
#include <error.h>
#include <sys/stat.h>
+#include <sys/types.h>
+#include <fts.h>
#include <openssl/x509.h>
{
int ret = CERT_SVC_ERR_NO_ERROR;
char **prev_field = NULL;
- int i = 0, l;
- memset(fld, 0, sizeof(fld));
+ int i = 0, l = 0;
+ if (fld == NULL) {
+ ret = CERT_SVC_ERR_INVALID_PARAMETER;
+ return ret;
+ }
+ memset(fld, 0, sizeof(cert_svc_name_fld_data));
while (str[i] != '\0') {
int tag_len;
char **field = __get_field_by_tag(str + i, &tag_len, fld);
else
(*fld).emailAddress = NULL;
-err:
return ret;
}
for(q = list; q != NULL; q = q->next) {
tmp2 = (cert_svc_cert_descriptor*)malloc(sizeof(cert_svc_cert_descriptor));
memset(tmp2, 0x00, sizeof(cert_svc_cert_descriptor));
-
+
_extract_certificate_data(q->certificate, tmp2);
if(!strncmp(tmp2->info.subjectStr, tmp1->info.issuerStr, strlen(tmp1->info.issuerStr))) { // success
SLOGE("[ERR][%s] Fail to extract certificate data.\n", __func__);
goto err;
}
-
+
if(!strncmp(certdesc->info.subjectStr, certdesc->info.issuerStr, strlen(certdesc->info.issuerStr))) { // self-signed
if(first_tag == 0) { // first cert is self-signed
start = start->next;
cert_svc_cert_descriptor* findRoot = NULL;
cert_svc_filename_list* fileNames = NULL;
cert_svc_mem_buff* CACert = NULL;
- int fileNum = 0;
int isCA = -1, isExpired = -1;
// variables for verification
int certNum = 0;
ret = _extract_certificate_data(p->certificate, findRoot);
}
- else
+ else
ret = _extract_certificate_data(certBuf, findRoot);
if(ret != CERT_SVC_ERR_NO_ERROR) {
ret = CERT_SVC_ERR_INVALID_OPERATION;
goto err;
}
-
+
certContent = certBuf->data;
d2i_X509(&targetCert, &certContent, certBuf->size);
-
+
q = sorted; // first item is the certificate that user want to verify
-
+
// insert all certificate(s) into chain
if(q != NULL) { // has 2 or more certificates
certIndex = 0;
ret = CERT_SVC_ERR_INVALID_CERTIFICATE;
goto err;
}
-
+
/* load signature and decode */
sigLen = strlen(signature);
decodedSigLen = ((sigLen / 4) * 3) + 1;
publicKeyAlgoLen = strlen(publicKeyAlgo);
certDesc->info.pubKeyAlgo = (unsigned char*)malloc(sizeof(unsigned char) * (publicKeyAlgoLen + 1));
memset(certDesc->info.pubKeyAlgo, 0x00, (publicKeyAlgoLen + 1));
- memcpy(certDesc->info.pubKeyAlgo, publicKeyAlgo, publicKeyAlgoLen);
+ memcpy(certDesc->info.pubKeyAlgo, publicKeyAlgo, publicKeyAlgoLen);
/* get public key */
if((evp = X509_get_pubkey(x)) == NULL) {
SLOGE("[ERR][%s] Public key is null.\n", __func__);
memset(certDesc->info.issuerUID, 0x00, (issuerUidLen + 1));
memcpy(certDesc->info.issuerUID, x->cert_info->issuerUID->data, issuerUidLen);
}
- else
+ else
certDesc->info.issuerUID = NULL;
/* get subject UID */
memset(certDesc->info.subjectUID, 0x00, (subjectUidLen + 1));
memcpy(certDesc->info.subjectUID, x->cert_info->subjectUID->data, subjectUidLen);
}
- else
+ else
certDesc->info.subjectUID = NULL;
/* get extension fields */
if(x->cert_info->extensions != NULL) {
certDesc->ext.fields[i].name = (unsigned char*)malloc(sizeof(unsigned char) * (extObjLen + 1));
memset(certDesc->ext.fields[i].name, 0x00, (extObjLen + 1));
memcpy(certDesc->ext.fields[i].name, extObject, extObjLen);
-
+
extValue = ext->value->data;
extValLen = ext->value->length;
certDesc->ext.fields[i].data = (unsigned char*)malloc(sizeof(unsigned char) * (extValLen + 1));
return ret;
}
-int get_filelist_recur(char* dirName, cert_svc_filename_list* fileNames, int* fileNum)
-{
- int ret = CERT_SVC_ERR_NO_ERROR;
- struct dirent **items;
- int nItems, i;
- char tmpDirName[CERT_SVC_MAX_FILE_NAME_SIZE];
- char tmpFileName[CERT_SVC_MAX_FILE_NAME_SIZE];
- cert_svc_filename_list* new = NULL;
- cert_svc_filename_list* p = NULL;
-
- /* find file path with location */
- if(chdir(dirName) < 0) {
- SLOGE("[ERR][%s] Fail to open directory: [%s]\n", __func__, dirName);
- perror("open dir");
- ret = CERT_SVC_ERR_INVALID_OPERATION;
- goto err;
- }
-
- /* get all items in current directory */
- nItems = scandir(".", &items, NULL, alphasort);
-
- for(i = 0; i < nItems; i++) {
- struct stat fstat;
-
- // ignore current dir, parent dir
- if(!strncmp(items[i]->d_name, ".", 1) || !strncmp(items[i]->d_name, "..", 2))
- continue;
-
- // if directory, recursive call
- stat(items[i]->d_name, &fstat);
- if((fstat.st_mode & S_IFDIR) == S_IFDIR) {
- memset(tmpDirName, 0x00, CERT_SVC_MAX_FILE_NAME_SIZE);
- strncpy(tmpDirName, dirName, strlen(dirName));
- strncat(tmpDirName, items[i]->d_name, strlen(items[i]->d_name));
- strncat(tmpDirName, "/", 1);
-
- if((ret = get_filelist_recur(tmpDirName, fileNames, fileNum)) != CERT_SVC_ERR_NO_ERROR) {
- SLOGE("[ERR][%s] Fail to search file.\n", __func__);
- goto err;
- }
- continue;
- }
- else { // if file, get filename into filelist
- memset(tmpFileName, 0x00, CERT_SVC_MAX_FILE_NAME_SIZE);
- strncpy(tmpFileName, dirName, strlen(dirName));
- strncat(tmpFileName, items[i]->d_name, strlen(items[i]->d_name));
-
- (*fileNum)++;
- p = fileNames;
-
- if(p->filename == NULL) {
- if(!(p->filename = (char*)malloc(sizeof(char) * CERT_SVC_MAX_FILE_NAME_SIZE))) {
- SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__);
- ret = CERT_SVC_ERR_MEMORY_ALLOCATION;
- goto err;
- }
- memset(p->filename, 0x00, CERT_SVC_MAX_FILE_NAME_SIZE);
- strncpy(p->filename, tmpFileName, strlen(tmpFileName));
- p->next = NULL;
- }
- else {
- while(p->next != NULL)
- p = p->next;
-
- new = (cert_svc_filename_list*)malloc(sizeof(cert_svc_filename_list));
- memset(new, 0x00, sizeof(cert_svc_filename_list));
- new->filename = (char*)malloc(sizeof(char) * CERT_SVC_MAX_FILE_NAME_SIZE);
- memset(new->filename, 0x00, CERT_SVC_MAX_FILE_NAME_SIZE);
-
- strncpy(new->filename, tmpFileName, strlen(tmpFileName));
- new->next = NULL;
-
- p->next = new;
- }
- }
- }
-
- chdir("..");
-
-err:
- for(i = 0; i < nItems; i++)
- free(items[i]);
- free(items);
-
- return ret;
-}
-
int search_data_field(search_field fldName, char* fldData, cert_svc_cert_descriptor* certDesc)
{
int ret = -1;
return ret;
}
-int get_all_certificates(cert_svc_filename_list* allCerts)
+int _get_all_certificates(char* const *paths, cert_svc_filename_list **lst) {
+ int ret = CERT_SVC_ERR_NO_ERROR;
+ FTS *fts = NULL;
+ FTSENT *ftsent;
+
+ char tmp[10];
+ int len;
+ cert_svc_filename_list *local = NULL;
+ cert_svc_filename_list *el;
+
+ if (NULL == (fts = fts_open(paths, FTS_LOGICAL, NULL))) {
+ ret = CERT_SVC_ERR_FILE_IO;
+ SLOGE("[ERR][%s] Fail to open directories.\n", __func__);
+ goto out;
+ }
+
+ while ((ftsent = fts_read(fts)) != NULL) {
+
+ if (ftsent->fts_info == FTS_ERR || ftsent->fts_info == FTS_NS) {
+ ret = CERT_SVC_ERR_FILE_IO;
+ SLOGE("[ERR][%s] Fail to read directories.\n", __func__);
+ goto out;
+ }
+
+ if (ftsent->fts_info != FTS_F)
+ continue;
+
+ if (-1 != readlink(ftsent->fts_path, tmp, 10))
+ continue;
+
+ el = (cert_svc_filename_list*)malloc(sizeof(cert_svc_filename_list));
+ if (!el) {
+ ret = CERT_SVC_ERR_MEMORY_ALLOCATION;
+ SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__);
+ goto out;
+ }
+ el->next = local;
+ local = el;
+
+ len = strlen(ftsent->fts_path);
+ local->filename = (char*)malloc(len+1);
+ if (!local->filename) {
+ ret = CERT_SVC_ERR_MEMORY_ALLOCATION;
+ SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__);
+ goto out;
+ }
+ strncpy(local->filename, ftsent->fts_path, len+1);
+ }
+
+ *lst = local;
+ local = NULL;
+
+out:
+ while (local) {
+ el = local;
+ local = local->next;
+ free(el->filename);
+ free(el);
+ }
+
+ if (fts != NULL)
+ fts_close(fts);
+ return ret;
+}
+
+int get_all_certificates(cert_svc_filename_list** allCerts)
{
- int ret = CERT_SVC_ERR_NO_ERROR;
- int fileNum = 0;
- char buf[1024] = {0, };
- getcwd(buf, 1024);
+ int ret;
+ char ** buffer[] = {CERT_SVC_SEARCH_PATH_RO, CERT_SVC_SEARCH_PATH_RW, NULL};
- if((ret = get_filelist_recur(CERT_SVC_SEARCH_PATH_RO, allCerts, &fileNum)) != CERT_SVC_ERR_NO_ERROR) {
- SLOGE("[ERR][%s] Fail to get filelist.\n", __func__);
- ret = CERT_SVC_ERR_INVALID_OPERATION;
- goto err;
- }
- if((ret = get_filelist_recur(CERT_SVC_SEARCH_PATH_RW, allCerts, &fileNum)) != CERT_SVC_ERR_NO_ERROR) {
- SLOGE("[ERR][%s] Fail to get filelist.\n", __func__);
- ret = CERT_SVC_ERR_INVALID_OPERATION;
- goto err;
- }
+ if (!allCerts) {
+ SLOGE("[ERR][%s] Invalid argument.\n", __func__);
+ return CERT_SVC_ERR_INVALID_PARAMETER;
+ }
-err:
- chdir(buf);
- return ret;
+ if ((ret = _get_all_certificates((char* const *) buffer, allCerts)) != CERT_SVC_ERR_NO_ERROR) {
+ SLOGE("[ERR][%s] Fail to get filelist.\n", __func__);
+ return ret;
+ }
+
+ return CERT_SVC_ERR_NO_ERROR;
}
int _search_certificate(cert_svc_filename_list** fileNames, search_field fldName, char* fldData)
int matched = 0;
struct stat file_info;
- /* get all certificates from device */
- if(!(allCerts = (cert_svc_filename_list*)malloc(sizeof(cert_svc_filename_list)))) {
- SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__);
- ret = CERT_SVC_ERR_MEMORY_ALLOCATION;
- goto err;
- }
- allCerts->filename = NULL;
- allCerts->next = NULL;
-
- if((ret = get_all_certificates(allCerts)) != CERT_SVC_ERR_NO_ERROR) {
+ if((ret = get_all_certificates(&allCerts)) != CERT_SVC_ERR_NO_ERROR) {
SLOGE("[ERR][%s] Fail to get all certificate file list, ret: [%d]\n", __func__, ret);
goto err;
}
while(1) {
if((lstat(p->filename, &file_info)) < 0) { // get file information
- SLOGE("[ERR][%s] Fail to get file information.\n", __func__);
+ SLOGE("[ERR][%s] Fail to get file(%s) information.\n", __func__, p->filename);
ret = CERT_SVC_ERR_INVALID_OPERATION;
goto err;
}
ret = CERT_SVC_ERR_MEMORY_ALLOCATION;
goto err;
}
- if(!(certDesc = (cert_svc_cert_descriptor*)malloc(sizeof(cert_svc_cert_descriptor)))) {
- SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__);
- ret = CERT_SVC_ERR_MEMORY_ALLOCATION;
- goto err;
- }
- // load content into descriptor buffer
+ // load content into buffer
if((ret = cert_svc_util_load_file_to_buffer(p->filename, certBuf)) != CERT_SVC_ERR_NO_ERROR) {
SLOGE("[ERR][%s] Fail to load file to buffer, filename: [%s], ret: [%d]\n", __func__, p->filename, ret);
free(certBuf);
certBuf = NULL;
- free(certDesc);
- certDesc = NULL;
goto fail_to_load_file;
}
+
+ // allocate memory
+ if(!(certDesc = (cert_svc_cert_descriptor*)malloc(sizeof(cert_svc_cert_descriptor)))) {
+ SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__);
+ ret = CERT_SVC_ERR_MEMORY_ALLOCATION;
+ goto err;
+ }
+
+ // load content into descriptor buffer
if((ret = _extract_certificate_data(certBuf, certDesc)) != CERT_SVC_ERR_NO_ERROR) {
SLOGE("[ERR][%s] Fail to extract certificate data, filename: [%s], ret: [%d]\n", __func__, p->filename, ret);
goto fail_to_extract_file;
if(!(new->filename = (char*)malloc(sizeof(char) * CERT_SVC_MAX_FILE_NAME_SIZE))) {
SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__);
ret = CERT_SVC_ERR_MEMORY_ALLOCATION;
+ free(new);
goto err;
}
memset(new->filename, 0x00, CERT_SVC_MAX_FILE_NAME_SIZE);
-
+
strncpy(new->filename, p->filename, strlen(p->filename));
new->next = NULL;
while(1) {
curCert = startCert;
startCert = startCert->next;
-
- if(curCert->certificate->data != NULL) {
- free(curCert->certificate->data);
- curCert->certificate->data = NULL;
- }
+
if(curCert->certificate != NULL) {
+ if(curCert->certificate->data != NULL) {
+ free(curCert->certificate->data);
+ curCert->certificate->data = NULL;
+ }
free(curCert->certificate);
curCert->certificate = NULL;
}
+
curCert->next = NULL;
+
if(curCert != NULL) {
free(curCert);
curCert = NULL;
memset(pathLocation, 0x00, CERT_SVC_MAX_FILE_NAME_SIZE);
if(location == NULL) // use default path
- strncpy(buf, CERT_SVC_STORE_PATH_DEFAULT, strlen(CERT_SVC_STORE_PATH_DEFAULT));
+ strncpy(buf, CERT_SVC_STORE_PATH_DEFAULT, strlen(CERT_SVC_STORE_PATH_DEFAULT)+1);
else {
strncpy(pathLocation, location, strlen(location));
- strncpy(buf, CERT_SVC_STORE_PATH, strlen(CERT_SVC_STORE_PATH));
+ strncpy(buf, CERT_SVC_STORE_PATH, strlen(CERT_SVC_STORE_PATH)+1);
token = strtok(pathLocation, seps);
while(token) {
strncat(buf, token, strlen(token));
/*
* certification service
*
- * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
* Contact: Kidong Kim <kd0228.kim@samsung.com>
*
#include "cert-service.h"
#include "cert-service-util.h"
#include "cert-service-debug.h"
+#include "cert-service-process.h"
#ifndef CERT_SVC_API
#define CERT_SVC_API __attribute__((visibility("default")))
#endif
+#define CERT_BODY_PREFIX "-----BEGIN CERTIFICATE-----"
+#define CERT_BODY_SUFIX "-----END CERTIFICATE-----"
+#define ICERT_BODY_PREFIX "-----BEGIN TRUSTED CERTIFICATE-----"
+#define ICERT_BODY_SUFIX "-----END TRUSTED CERTIFICATE-----"
+
/* Tables for base64 operation */
static const char base64Table[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 0 ~ 15
int get_content_into_buf_PEM(unsigned char* content, cert_svc_mem_buff* cert)
{
int ret = CERT_SVC_ERR_NO_ERROR;
- char* startPEM = "-----BEGIN CERTIFICATE-----";
- char* endPEM = "-----END CERTIFICATE-----";
- int size = 0;
+ char *startPEM, *endPEM;
+ long size = 0;
char* original = NULL;
char* decoded = NULL;
int decodedSize = 0;
int i = 0, j = 0;
- startPEM = strstr((const char*)content, startPEM) + strlen(startPEM) + 1;
- endPEM = strstr((const char*)content, endPEM) - 1;
- size = (int)endPEM - (int)startPEM;
+ if(!content) {
+ ret = CERT_SVC_ERR_INVALID_PARAMETER;
+ goto err;
+ }
+ startPEM = strstr((const char *)content, CERT_BODY_PREFIX);
+ startPEM = (startPEM) ? startPEM + strlen(CERT_BODY_PREFIX) : NULL;
+ endPEM = strstr((const char *)content, CERT_BODY_SUFIX);
+ if(!startPEM || !endPEM) {
+ startPEM = strstr((const char *)content, ICERT_BODY_PREFIX);
+ startPEM = (startPEM) ? startPEM + strlen(ICERT_BODY_PREFIX) : NULL;
+ endPEM = strstr((const char *)content, ICERT_BODY_SUFIX);
+ }
+ if(!startPEM || !endPEM) {
+ ret = CERT_SVC_ERR_UNKNOWN_ERROR;
+ goto err;
+ }
+ else {
+ ++startPEM;
+ --endPEM;
+ size = (long)endPEM - (long)startPEM;
+ }
if(!(original = (char*)malloc(sizeof(char) * (size + 1)))) {
SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__);
goto err;
}
memset(original, 0x00, (size + 1));
-
- for(i = 0; i < size; i++) {
+
+ for(i = 0, j = 0; i < size; i++) {
if(startPEM[i] != '\n')
original[j++] = startPEM[i];
}
memset(decoded, 0x00, decodedSize);
if((ret = cert_svc_util_base64_decode(original, size, decoded, &decodedSize)) != CERT_SVC_ERR_NO_ERROR) {
SLOGE("[ERR][%s] Fail to base64 decode.\n", __func__);
+ free(decoded);
ret = CERT_SVC_ERR_INVALID_OPERATION;
goto err;
}
cert->data = (unsigned char*)decoded;
cert->size = decodedSize;
-
+
err:
- if(original != NULL)
- free(original);
-
+ if(original != NULL)
+ free(original);
return ret;
}
err:
if(fp_in != NULL)
fclose(fp_in);
-
+
return ret;
}
+/* The dark side of cert-svc. */
+int cert_svc_util_get_extension(const char* filePath, cert_svc_mem_buff* certBuf) {
+ int ret = CERT_SVC_ERR_NO_ERROR;
+ FILE *in = NULL;
+ X509 *x = NULL;
+
+ if ((in = fopen(filePath, "r")) == NULL) {
+ SLOGE("[ERR] Error opening file %s\n", filePath);
+ ret = CERT_SVC_ERR_FILE_IO;
+ goto end;
+ }
+
+ if ((x = PEM_read_X509(in, NULL, NULL, NULL)) != NULL) {
+ strncpy(certBuf->type, "PEM", sizeof(certBuf->type));
+ goto end;
+ }
+
+ fseek(in, 0L, SEEK_SET);
+
+ if ((x = PEM_read_X509_AUX(in, NULL, NULL, NULL)) != NULL) {
+ strncpy(certBuf->type, "PEM", sizeof(certBuf->type));
+ goto end;
+ }
+
+ fseek(in, 0L, SEEK_SET);
+
+ if ((x = d2i_X509_fp(in, NULL)) != NULL) {
+ strncpy(certBuf->type, "DER", sizeof(certBuf->type));
+ goto end;
+ }
+
+ SLOGE("[ERR] Unknown file type: %s\n", filePath);
+ ret = CERT_SVC_ERR_FILE_IO;
+
+end:
+ if (in && fclose(in)) {
+ SLOGE("[ERR] Fail in fclose.");
+ ret = CERT_SVC_ERR_FILE_IO;
+ }
+ X509_free(x);
+ return ret;
+}
+
int cert_svc_util_load_file_to_buffer(const char* filePath, cert_svc_mem_buff* certBuf)
{
int ret = CERT_SVC_ERR_NO_ERROR;
goto err;
}
- if(!(content = (unsigned char*)malloc(sizeof(unsigned char) * (unsigned int)fileSize))) {
+ if(!(content = (unsigned char*)malloc(sizeof(unsigned char) * (unsigned int)(fileSize + 1)))) {
SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__);
ret = CERT_SVC_ERR_MEMORY_ALLOCATION;
goto err;
}
+ memset(content, 0x00, (fileSize + 1)); //ensuring that content[] will be NULL terminated
if(fread(content, sizeof(unsigned char), fileSize, fp_in) != fileSize) {
SLOGE("[ERR][%s] Fail to read file, [%s]\n", __func__, filePath);
ret = CERT_SVC_ERR_FILE_IO;
goto err;
}
-
+
/* find out certificate type */
memset(certBuf->type, 0x00, 4);
- extension = filePath + (strlen(filePath) - 3);
- if(!strncmp(extension, "pem", 3) || !strncmp(extension, "PEM", 3) ||
- !strncmp(extension, "cer", 3) || !strncmp(extension, "CER", 3) ||
- !strncmp(extension, "crt", 3) || !strncmp(extension, "CRT", 3))
- strncpy(certBuf->type, "PEM", 3);
- else if(!strncmp(extension, "der", 3) || !strncmp(extension, "DER", 3))
- strncpy(certBuf->type, "DER", 3);
- else {
- SLOGE("[ERR][%s] Cannot get certificate type, [%s]\n", __func__, extension);
- ret = CERT_SVC_ERR_INVALID_CERTIFICATE;
- goto err;
- }
-
+ if (cert_svc_util_get_extension(filePath, certBuf) != CERT_SVC_ERR_NO_ERROR) {
+ SLOGE("[ERR] cert_svc_util_get_extension failed to identify %s\n", filePath);
+ ret = CERT_SVC_ERR_FILE_IO;
+ goto err;
+ }
+
/* load file into buffer */
- if(!strncmp(certBuf->type, "PEM", 3)) { // PEM format
+ if(!strncmp(certBuf->type, "PEM", sizeof(certBuf->type))) { // PEM format
if((ret = get_content_into_buf_PEM(content, certBuf)) != CERT_SVC_ERR_NO_ERROR) {
SLOGE("[ERR][%s] Fail to load file to buffer, [%s]\n", __func__, filePath);
goto err;
}
}
- else if(!strncmp(certBuf->type, "DER", 3)) { // DER format
+ else if(!strncmp(certBuf->type, "DER", sizeof(certBuf->type))) { // DER format
if((ret = get_content_into_buf_DER(content, certBuf)) != CERT_SVC_ERR_NO_ERROR) {
SLOGE("[ERR][%s] Fail to load file to buffer, [%s]\n", __func__, filePath);
goto err;
}
}
-
+
err:
if(fp_in != NULL)
fclose(fp_in);
if(content != NULL)
free(content);
-
+
return ret;
}
-int push_cert_into_linked_list(cert_svc_linked_list* certLink, X509* popedCert)
+int push_cert_into_linked_list(cert_svc_linked_list** certLink, X509* popedCert)
{
int ret = CERT_SVC_ERR_NO_ERROR;
cert_svc_linked_list* cur = NULL;
}
if(!(new->certificate = (cert_svc_mem_buff*)malloc(sizeof(cert_svc_mem_buff)))) {
SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__);
+ free(new);
ret = CERT_SVC_ERR_MEMORY_ALLOCATION;
goto err;
}
/* get certificate data and store in certLink */
if((certLen = i2d_X509(popedCert, NULL)) < 0) {
SLOGE("[ERR][%s] Fail to convert certificate.\n", __func__);
+ release_cert_list(new);
ret = CERT_SVC_ERR_INVALID_OPERATION;
goto err;
}
if(!(bufCert = (unsigned char*)malloc(sizeof(unsigned char) * certLen))) {
SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__);
ret = CERT_SVC_ERR_MEMORY_ALLOCATION;
+ release_cert_list(new);
goto err;
}
pCert = bufCert;
new->certificate->data = bufCert;
new->certificate->size = certLen;
- /* attach to linked list */
- cur = certLink;
- if(cur == NULL) { // first item
- cur = new;
+ if(NULL == *certLink) { // first item
+ *certLink = new;
}
else {
- while(1) {
- if(cur->next == NULL)
- break;
+ /* attach to linked list */
+ cur = *certLink;
+ while(cur->next)
cur = cur->next;
- }
cur->next = new;
}
ret = CERT_SVC_ERR_INVALID_CERTIFICATE;
goto err;
}
-
+
/* parse PKCS#12 certificate */
if((ret = PKCS12_parse(p12, passPhrase, &pkey, &cert, &ca)) != 1) {
SLOGE("[ERR][%s] Fail to parse PKCS#12 certificate.\n", __func__);
ret = CERT_SVC_ERR_NO_ERROR;
/* find out certificate type */
memset(certBuf->type, 0x00, 4);
- strncpy(certBuf->type, "PFX", 3);
-
+ strncpy(certBuf->type, "PFX", sizeof(certBuf->type));
+
/* load certificate into buffer */
if((certLen = i2d_X509(cert, NULL)) < 0) {
SLOGE("[ERR][%s] Fail to convert certificate.\n", __func__);
goto err;
}
}
-
+
err:
if(fp_in != NULL)
fclose(fp_in);
if(ca != NULL)
sk_X509_pop_free(ca, X509_free);
EVP_cleanup();
-
+
return ret;
}
int ret = CERT_SVC_ERR_NO_ERROR;
int inputLen = 0, i = 0;
char* cur = NULL;
-
+
if((in == NULL) || (inLen < 1)) {
SLOGE("[ERR][%s] Check your parameter.\n", __func__);
ret = CERT_SVC_ERR_INVALID_PARAMETER;
out[i] = '\0';
(*outLen) = i;
-err:
+err:
return ret;
}
CERT_SVC_API
else
tmpBuf[j] = base64DecodeTable[(int)cur[j]];
}
-
+
out[i++] = ((tmpBuf[0] & 0x3f) << 2) + ((tmpBuf[1] & 0x30) >> 4);
out[i++] = ((tmpBuf[1] & 0x0f) << 4) + ((tmpBuf[2] & 0x3c) >> 2);
out[i++] = ((tmpBuf[2] & 0x03) << 6) + (tmpBuf[3] & 0x3f);
int cert_svc_verify_certificate(CERT_CONTEXT* ctx, int* validity)
{
int ret = CERT_SVC_ERR_NO_ERROR;
- int i = 0, first = 0;
if((ctx == NULL) || (ctx->certBuf == NULL)) {
SLOGE("[ERR][%s] Check your parameter. Cannot find certificate.\n", __func__);
int cert_svc_verify_signature(CERT_CONTEXT* ctx, unsigned char* message, int msgLen, unsigned char* signature, char* algo, int* validity)
{
int ret = CERT_SVC_ERR_NO_ERROR;
- cert_svc_mem_buff* certBuf = NULL;
if((message == NULL) || (signature == NULL) || (ctx == NULL) || (ctx->certBuf == NULL)) {
SLOGE("[ERR][%s] Invalid parameter, please check your parameter\n", __func__);
int cert_svc_search_certificate(CERT_CONTEXT* ctx, search_field fldName, char* fldData)
{
int ret = CERT_SVC_ERR_NO_ERROR;
- int i = 0;
/* check parameter */
if((ctx == NULL) || (fldName < SEARCH_FIELD_START ) || (fldName > SEARCH_FIELD_END) || (fldData == NULL)) {
CERT_SVC_API
CERT_CONTEXT* cert_svc_cert_context_init()
{
- int ret = CERT_SVC_ERR_NO_ERROR;
CERT_CONTEXT* ctx = NULL;
if(!(ctx = (CERT_CONTEXT*)malloc(sizeof(CERT_CONTEXT)))) {
int cert_svc_cert_context_final(CERT_CONTEXT* context)
{
int ret = CERT_SVC_ERR_NO_ERROR;
- cert_svc_linked_list* pLink = NULL;
- cert_svc_filename_list* pFile = NULL;
if(context == NULL) // already be freed
goto err;
if((ret = cert_svc_util_base64_decode(buf, size, decodedStr, &decodedSize)) != CERT_SVC_ERR_NO_ERROR) {
SLOGE("[ERR][%s] Fail to decode string, ret: [%d]\n", __func__, ret);
ret = CERT_SVC_ERR_INVALID_OPERATION;
+ free(decodedStr);
goto err;
}
}
if(!(new->certificate = (cert_svc_mem_buff*)malloc(sizeof(cert_svc_mem_buff)))) {
SLOGE("[ERR][%s] Fail to allcate memory.\n", __func__);
+ free(new);
ret = CERT_SVC_ERR_MEMORY_ALLOCATION;
goto err;
}
if(!(decodedStr = (char*)malloc(sizeof(char) * decodedSize))) {
SLOGE("[ERR][%s] Fail to allocate memory.\n", __func__);
+ release_cert_list(new);
ret = CERT_SVC_ERR_MEMORY_ALLOCATION;
goto err;
}
/* decode */
if((ret = cert_svc_util_base64_decode(buf, size, decodedStr, &decodedSize)) != CERT_SVC_ERR_NO_ERROR) {
SLOGE("[ERR][%s] Fail to decode string, ret: [%d]\n", __func__, ret);
+ release_cert_list(new);
+ free(decodedStr);
ret = CERT_SVC_ERR_INVALID_OPERATION;
goto err;
}
ctx->certLink = new;
else {
cur = ctx->certLink;
- while(1) {
- if(cur->next == NULL)
- break;
+ while(cur->next)
cur = cur->next;
- }
-
cur->next = new;
}
if(!(new->certificate = (cert_svc_mem_buff*)malloc(sizeof(cert_svc_mem_buff)))) {
SLOGE("[ERR][%s] Fail to allcate memory.\n", __func__);
ret = CERT_SVC_ERR_MEMORY_ALLOCATION;
+ free(new);
goto err;
}
memset(new->certificate, 0x00, sizeof(cert_svc_mem_buff));
/* get content to ctx->certBuf */
if((ret = cert_svc_util_load_file_to_buffer(filePath, new->certificate)) != CERT_SVC_ERR_NO_ERROR) {
SLOGE("[ERR][%s] Fail to load file, filepath: [%s], ret: [%d]\n", __func__, filePath, ret);
+ release_cert_list(new);
ret = CERT_SVC_ERR_INVALID_OPERATION;
goto err;
}
#include <time.h>
#include <dirent.h>
#include <error.h>
+#include <limits.h>
#include <sys/stat.h>
#include <sys/types.h>
if(rmdir(path) != 0) {
fprintf(stderr, "[ERR][%s] Fail to remove directory, [%s]\n", __func__, path);
- ret = DPS_FILE_ERR;
- goto err;
- }
+ ret = DPS_FILE_ERR;
+ goto err;
+ }
err:
if(dir != NULL) closedir(dir);
FILE* fp_control = NULL;
FILE* fp_data = NULL;
FILE* fp_sig = NULL;
- char tempbuf[64];
- char filename[16];
- char filelen[10];
+ /* size+1 for null termination */
+ char tempbuf[65];
+ char filename[17];
+ char filelen[11];
char* buf = NULL;
- memset(tempbuf, 0x00, 64);
- memset(filename, 0x00, 16);
- memset(filelen, 0x00, 10);
+ if (fp_deb == NULL) {
+ fprintf(stderr, "[ERR] Null file pointer passed to function\n");
+ ret = DPS_FILE_ERR;
+ return ret;
+ }
+
+ memset(tempbuf, 0x00, 65);
+ memset(filename, 0x00, 17);
+ memset(filelen, 0x00, 11);
if(!(fp_control = fopen("./temp/control.tar.gz", "wb"))) {
fprintf(stderr, "[ERR][%s] Fail to open file, [control.tar.gz]\n", __func__);
while(fgets(tempbuf, 64, fp_deb)) {
strncpy(filename, tempbuf, 16);
- if(memcmp(filename, "!<arch>\n", 8) == 0)
+ if(memcmp(filename, "!<arch>\n", 8) == 0) {
+ memset(tempbuf, 0x00, 65);
continue;
+ }
if((memcmp(filename, "control.tar.gz", 14) == 0) ||
(memcmp(filename, "data.tar.gz", 11) == 0) ||
(memcmp(filename, "_sigandcert", 11) == 0)
) {
strncpy(filelen, tempbuf + 48, 10);
size = strtoul(filelen, NULL, 10);
-
+ if((int)size <= 0) {
+ fprintf(stderr, "[ERR][%s] Fail to get filelen\n", __func__);
+ ret = DPS_FILE_ERR;
+ goto err;
+ }
if(!(buf = (char*)malloc(sizeof(char) * (int)size))) {
fprintf(stderr, "[ERR][%s] Fail to allocate memory\n", __func__);
ret = DPS_MEMORY_ERR;
int ret = DPS_OPERATION_SUCCESS;
fseek(fp_file, 0L, SEEK_END);
- filelen = ftell(fp_file);
+ if (-1 == (filelen = ftell(fp_file))) {
+ fprintf(stderr, "[ERR] Error returned by ftell()");
+ ret = DPS_FILE_ERR;
+ goto err;
+ }
fseek(fp_file, 0L, SEEK_SET);
if(!(in = (char*)malloc(sizeof(char) * (filelen + 1)))) {
err:
if(in != NULL) free(in);
if(hashout != NULL) free(hashout);
-
+
return ret;
}
char* token = NULL;
char seps[] = " \t\n\r";
char buf[16];
- int ret = DPS_OPERATION_SUCCESS;
memset(buf, 0x00, 16);
if(!(fp_info = fopen(TARGET_INFO, "r"))) { // error
fprintf(stderr, "[ERR][%s] Fail to open file, [%s]\n", __func__, TARGET_INFO);
- ret = DPS_FILE_ERR;
- goto err;
+ return DPS_FILE_ERR;
}
fgets(buf, 16, fp_info);
if(buf[0] == '0') { // not used
// do nothing
- strncpy(info, "NOT USED", 8);
+ strncpy(info, "NOT USED", sizeof("NOT USED"));
}
else if(buf[0] == '1') {
memset(buf, 0x00, 16);
}
else {
fprintf(stderr, "[ERR][%s] Check your targetinfo file.\n", __func__);
- ret = DPS_INVALID_OPERATION;
- goto err;
+ fclose(fp_info);
+ return DPS_INVALID_OPERATION;
}
-err:
- return ret;
+ fclose(fp_info);
+ return DPS_OPERATION_SUCCESS;
}
int generate_sdk_cert(int argc, const char** argv)
int ret = DPS_OPERATION_SUCCESS;
int ch = 0, i = 0;
int certwrite = 0;
- unsigned long int privlen = 0;
+ unsigned long int privlen = 0;
unsigned long int encodedlen = 0;
unsigned long int certlen = 0;
unsigned long int sigfilelen = 0;
privlen = ftell(fp_priv);
fseek(fp_priv, 0L, SEEK_SET);
+ if((int)privlen <= 0){
+ fprintf(stderr, "[ERR][%s] Fail to get file lengh\n", __func__);
+ ret = DPS_FILE_ERR;
+ goto err;
+ }
+
if(!(prikey = (char*)malloc(sizeof(char) * (int)privlen))) {
fprintf(stderr, "[ERR][%s] Fail to allocate memory\n", __func__);
ret = DPS_FILE_ERR;
ret = DPS_FILE_ERR;
goto err;
}
+
fseek(fp_cert, 0L, SEEK_END);
+
+ if(ftell(fp_cert) < 0) {
+ fprintf(stderr, "[ERR][%s] Fail to find EOF\n", __func__);
+ ret = DPS_FILE_ERR;
+ goto err;
+ }
+
certlen = ftell(fp_cert);
fseek(fp_cert, 0L, SEEK_SET);
}
/* insert file into deb archive */
- sigfilelen = ftell(fp_sig);
+ if (-1 == (sigfilelen = ftell(fp_sig))) {
+ fprintf(stderr, "[ERR] Failed to get filesize by ftell()\n");
+ ret = DPS_FILE_ERR;
+ goto err;
+ }
+
fseek(fp_sig, 0L, SEEK_SET);
fseek(fp_deb, 0L, SEEK_END);
fprintf(stderr, "[ERR][%s] Fail to make temporary directory, [%s]\n", __func__, "./temp");
ret = DPS_INVALID_OPERATION;
goto err;
- }
-
+ }
+
/* extract files from .deb */
if((fp_deb = fopen(argv[0], "rb")) == NULL) {
fprintf(stderr, "[ERR][%s] Fail to open file. [%s]\n", __func__, argv[0]);
ret = DPS_FILE_ERR;
goto err;
}
-
+
if((ret = get_files_from_deb(fp_deb)) != DPS_OPERATION_SUCCESS) {
fprintf(stderr, "[ERR][%s] Fail to extract files.\n", __func__);
goto err;
}
-
+
/* get msg, sig, cert from_sigandcert */
if((fp_sig = fopen("./temp/_sigandcert", "r")) == NULL) {
fprintf(stderr, "[ERR][%s] Fail to open file. [_sigandcert]\n", __func__);
ret = DPS_FILE_ERR;
goto err;
}
-
+
memset(filebuf, 0x00, 64);
while(fgets(filebuf, 64, fp_sig) != NULL) {
- if(!strncmp(filebuf, "MESSAGES:", 9)) {
- fgets(filebuf, 64, fp_sig);
- msglen = (int)strtoul(filebuf, NULL, 10);
- msg = (char*)malloc(sizeof(char) * (msglen + 1));
- memset(msg, 0x00, (msglen + 1));
- if(fread(msg, sizeof(char), msglen, fp_sig) != msglen) {
- fprintf(stderr, "[ERR][%s] Fail to get contents from file, [messages]\n", __func__);
- ret = DPS_INVALID_OPERATION;
- goto err;
- }
- }
- else if(!strncmp(filebuf, "SIGNATURE:", 10)) {
- fgets(filebuf, 64, fp_sig);
- siglen = (int)strtoul(filebuf, NULL, 10);
- sig = (char*)malloc(sizeof(char) * (siglen + 1));
- memset(sig, 0x00, (siglen + 1));
- if(fread(sig, sizeof(char), siglen, fp_sig) != siglen) {
- fprintf(stderr, "[ERR][%s] Fail to get contents from file, [signature]\n", __func__);
- ret = DPS_INVALID_OPERATION;
- goto err;
- }
- }
- else if(!strncmp(filebuf, "CERTIFICATE:", 12)) {
- fgets(filebuf, 64, fp_sig);
- certlen = (int)strtoul(filebuf, NULL, 10);
- cert = (char*)malloc(sizeof(char) * (certlen + 1));
- memset(cert, 0x00, (certlen + 1));
- if(fread(cert, sizeof(char), certlen, fp_sig) != certlen) {
- fprintf(stderr, "[ERR][%s] Fail to get contents from file, [certificate]\n", __func__);
- ret = DPS_INVALID_OPERATION;
- goto err;
- }
- }
+ if(!strncmp(filebuf, "MESSAGES:", 9)) {
+ fgets(filebuf, 64, fp_sig);
+ msglen = (int)strtoul(filebuf, NULL, 10);
+ if ((msglen < 1) || (msglen >= INT_MAX)) {
+ fprintf(stderr, "[ERR][%s] Fail to get length of certificate\n", __func__);
+ ret = DPS_INVALID_OPERATION;
+ goto err;
+ }
+
+ msg = (char*)malloc(sizeof(char) * (msglen + 1));
+ if(!msg){
+ ret = DPS_INVALID_OPERATION;
+ goto err;
+ }
+
+ memset(msg, 0x00, (msglen + 1));
+ if(fread(msg, sizeof(char), msglen, fp_sig) != msglen) {
+ fprintf(stderr, "[ERR][%s] Fail to get contents from file, [messages]\n", __func__);
+ ret = DPS_INVALID_OPERATION;
+ goto err;
+ }
+
+ free(msg);
+ msg = NULL;
+ }
+ else if(!strncmp(filebuf, "SIGNATURE:", 10)) {
+ fgets(filebuf, 64, fp_sig);
+ siglen = (int)strtoul(filebuf, NULL, 10);
+ if ((siglen < 1) || (siglen >= INT_MAX)) {
+ fprintf(stderr, "[ERR][%s] Fail to get length of certificate\n", __func__);
+ ret = DPS_INVALID_OPERATION;
+ goto err;
+ }
+ sig = (char*)malloc(sizeof(char) * (siglen + 1));
+ if(!sig){
+ ret = DPS_INVALID_OPERATION;
+ goto err;
+ }
+
+ memset(sig, 0x00, (siglen + 1));
+ if(fread(sig, sizeof(char), siglen, fp_sig) != siglen) {
+ fprintf(stderr, "[ERR][%s] Fail to get contents from file, [signature]\n", __func__);
+ ret = DPS_INVALID_OPERATION;
+ goto err;
+ }
+
+ free(sig);
+ sig = NULL;
+ }
+ else if(!strncmp(filebuf, "CERTIFICATE:", 12)) {
+ fgets(filebuf, 64, fp_sig);
+ certlen = (int)strtoul(filebuf, NULL, 10);
+ if ((certlen < 1) || (certlen >= INT_MAX)) {
+ fprintf(stderr, "[ERR][%s] Fail to get length of certificate\n", __func__);
+ ret = DPS_INVALID_OPERATION;
+ goto err;
+ }
+ cert = (char*)malloc(sizeof(char) * (certlen + 1));
+ memset(cert, 0x00, (certlen + 1));
+ if(fread(cert, sizeof(char), certlen, fp_sig) != certlen) {
+ fprintf(stderr, "[ERR][%s] Fail to get contents from file, [certificate]\n", __func__);
+ ret = DPS_INVALID_OPERATION;
+ goto err;
+ }
+ free(cert);
+ cert = NULL;
+ }
}
/* get certificate data */
}
}
}
-
+
/* verify certificate */
if((ret = cert_svc_verify_certificate(ctx, &val_cert)) != CERT_SVC_ERR_NO_ERROR) {
fprintf(stderr, "[ERR][%s] Fail to verify certificate, [%d]\n", __func__, ret);
if(msg != NULL) free(msg);
if(sig != NULL) free(sig);
if(cert != NULL) free(cert);
- if(target_info != NULL) free(target_info);
+ if(target_info != NULL) free(target_info);
cert_svc_cert_context_final(ctx);
-
+
return ret;
}
--- /dev/null
+#DB vcore
+PKG_CHECK_MODULES(VCORE_DB_DEP
+ dpl-efl
+ REQUIRED)
+
+ADD_CUSTOM_COMMAND(
+ OUTPUT ${CMAKE_BINARY_DIR}/vcore/src/database_checksum_vcore.h
+ COMMAND ${CMAKE_SOURCE_DIR}/vcore/src/orm/gen_db_md5.sh
+ ARGS ${CMAKE_BINARY_DIR}/vcore/src/database_checksum_vcore.h
+ ${CMAKE_SOURCE_DIR}/vcore/src/orm/vcore_db
+ DEPENDS ${CMAKE_SOURCE_DIR}/vcore/src/orm/vcore_db
+ ${CMAKE_SOURCE_DIR}/vcore/src/orm/gen_db_md5.sh
+ COMMENT "Generating VCORE database checksum"
+ )
+
+STRING(REPLACE ";" ":" DEPENDENCIES "${VCORE_DB_DEP_INCLUDE_DIRS}")
+
+ADD_CUSTOM_COMMAND( OUTPUT .cert_svc_vcore.db
+ COMMAND rm -f ${CMAKE_CURRENT_BINARY_DIR}/.cert_svc_vcore.db
+ COMMAND CPATH=${DEPENDENCIES} gcc -Wall -include ${CMAKE_BINARY_DIR}/vcore/src/database_checksum_vcore.h -I${PROJECT_SOURCE_DIR}/vcore/src/orm -E ${PROJECT_SOURCE_DIR}/vcore/src/orm/vcore_db_sql_generator.h | grep --invert-match "^#" > ${CMAKE_CURRENT_BINARY_DIR}/cert_svc_vcore_db.sql
+ COMMAND sqlite3 ${CMAKE_CURRENT_BINARY_DIR}/.cert_svc_vcore.db ".read ${CMAKE_CURRENT_BINARY_DIR}/cert_svc_vcore_db.sql" || rm -f ${CMAKE_CURRENT_BINARY_DIR}/.cert_svc_vcore.db
+ DEPENDS ${CMAKE_BINARY_DIR}/vcore/src/database_checksum_vcore.h ${PROJECT_SOURCE_DIR}/vcore/src/orm/vcore_db_sql_generator.h ${PROJECT_SOURCE_DIR}/vcore/src/orm/vcore_db
+ )
+
+ADD_CUSTOM_COMMAND( OUTPUT .cert_svc_vcore.db-journal
+ COMMAND touch
+ ARGS ${CMAKE_CURRENT_BINARY_DIR}/.cert_svc_vcore.db-journal
+ )
+
+ADD_CUSTOM_TARGET(Sqlite3DbVCORE ALL DEPENDS .cert_svc_vcore.db .cert_svc_vcore.db-journal)
+
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/cert_svc_vcore_db.sql
+ DESTINATION /usr/share/cert-svc/
+ )
+
+ADD_SUBDIRECTORY(src)
--- /dev/null
+
+
+
+PRAGMA foreign_keys = ON; BEGIN TRANSACTION;
+
+
+
+CREATE TABLE OCSPResponseStorage (
+ cert_chain TEXT not null,
+ end_entity_check INT ,
+ ocsp_status INT ,
+ next_update_time BIGINT ,
+ PRIMARY KEY(cert_chain, end_entity_check) ,
+
+
+CHECK(1) );
+
+CREATE TABLE CRLResponseStorage (
+ distribution_point TEXT primary key not null,
+ crl_body TEXT not null,
+ next_update_time BIGINT ,
+CHECK(1) );
+
+COMMIT;
+BEGIN TRANSACTION; CREATE TABLE DB_VERSION_6d8092083d41289ab1c349aeaad617bc (version INT); COMMIT;
+
+
--- /dev/null
+INCLUDE(FindPkgConfig)
+
+PKG_CHECK_MODULES(VCORE_DEPS
+ dpl-efl
+ dpl-db-efl
+ ecore
+ appcore-efl
+ libxml-2.0
+ libsoup-2.4
+ libpcre
+ libpcrecpp
+ openssl
+ xmlsec1
+ secure-storage
+ REQUIRED)
+
+SET(VCORE_DIR
+ ${PROJECT_SOURCE_DIR}/vcore
+ )
+
+SET(VCORE_SRC_DIR
+ ${VCORE_DIR}/src/vcore
+ )
+
+SET(VCORE_SOURCES
+ ${VCORE_SRC_DIR}/api.cpp
+ ${VCORE_SRC_DIR}/Base64.cpp
+ ${VCORE_SRC_DIR}/CachedCRL.cpp
+ ${VCORE_SRC_DIR}/CachedOCSP.cpp
+ ${VCORE_SRC_DIR}/Certificate.cpp
+ ${VCORE_SRC_DIR}/CertificateCacheDAO.cpp
+ ${VCORE_SRC_DIR}/CertificateCollection.cpp
+ ${VCORE_SRC_DIR}/CertificateConfigReader.cpp
+ ${VCORE_SRC_DIR}/CertificateLoader.cpp
+ ${VCORE_SRC_DIR}/CertificateVerifier.cpp
+ ${VCORE_SRC_DIR}/CertStoreType.cpp
+ ${VCORE_SRC_DIR}/Config.cpp
+ ${VCORE_SRC_DIR}/CRL.cpp
+ ${VCORE_SRC_DIR}/CRLImpl.cpp
+ ${VCORE_SRC_DIR}/CRLCacheDAO.cpp
+ ${VCORE_SRC_DIR}/CryptoHash.cpp
+ ${VCORE_SRC_DIR}/Database.cpp
+ ${VCORE_SRC_DIR}/DeveloperModeValidator.cpp
+ ${VCORE_SRC_DIR}/OCSP.cpp
+ ${VCORE_SRC_DIR}/OCSPImpl.cpp
+ ${VCORE_SRC_DIR}/OCSPCertMgrUtil.cpp
+ ${VCORE_SRC_DIR}/OCSPUtil.c
+ ${VCORE_SRC_DIR}/ReferenceValidator.cpp
+ ${VCORE_SRC_DIR}/RevocationCheckerBase.cpp
+ ${VCORE_SRC_DIR}/SaxReader.cpp
+ ${VCORE_SRC_DIR}/SignatureFinder.cpp
+ ${VCORE_SRC_DIR}/SignatureReader.cpp
+ ${VCORE_SRC_DIR}/SoupMessageSendBase.cpp
+ ${VCORE_SRC_DIR}/SoupMessageSendSync.cpp
+ ${VCORE_SRC_DIR}/SoupMessageSendAsync.cpp
+ ${VCORE_SRC_DIR}/TimeConversion.cpp
+ ${VCORE_SRC_DIR}/VerificationStatus.cpp
+ ${VCORE_SRC_DIR}/ValidatorFactories.cpp
+ ${VCORE_SRC_DIR}/VCore.cpp
+ ${VCORE_SRC_DIR}/WrtSignatureValidator.cpp
+ ${VCORE_SRC_DIR}/XmlsecAdapter.cpp
+ ${VCORE_SRC_DIR}/pkcs12.c
+ )
+
+SET(VCORE_INCLUDES
+ ${VCORE_DEPS_INCLUDE_DIRS}
+ ${VCORE_SRC_DIR}
+ ${VCORE_DIR}/src
+ ${VCORE_DIR}/src/orm
+ ${VCORE_DIR}/src/legacy
+ ${CMAKE_BINARY_DIR}/vcore/src
+ )
+
+ADD_DEFINITIONS(${VCORE_DEPS_CFLAGS})
+ADD_DEFINITIONS(${VCORE_DEPS_CFLAGS_OTHER})
+ADD_DEFINITIONS("-DSEPARATED_SINGLETON_IMPLEMENTATION")
+ADD_DEFINITIONS("-DDPL_LOGS_ENABLED")
+
+INCLUDE_DIRECTORIES(${VCORE_INCLUDES})
+
+# cert-svc headers
+INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include)
+
+ADD_LIBRARY(${TARGET_VCORE_LIB} SHARED ${VCORE_SOURCES})
+SET_TARGET_PROPERTIES(${TARGET_VCORE_LIB} PROPERTIES
+ SOVERSION ${SO_VERSION}
+ VERSION ${VERSION})
+
+ADD_DEPENDENCIES(${TARGET_VCORE_LIB} Sqlite3DbWTF)
+
+TARGET_LINK_LIBRARIES(${TARGET_VCORE_LIB}
+ ${VCORE_DEPS_LIBRARIES}
+ ${TARGET_CERT_SVC_LIB}
+ )
+
+INSTALL(TARGETS ${TARGET_VCORE_LIB}
+ DESTINATION ${LIBDIR}
+ )
+
+INSTALL(FILES
+ ${VCORE_SRC_DIR}/Base64.h
+ ${VCORE_SRC_DIR}/CachedCRL.h
+ ${VCORE_SRC_DIR}/CachedOCSP.h
+ ${VCORE_SRC_DIR}/Certificate.h
+ ${VCORE_SRC_DIR}/CertificateCollection.h
+ ${VCORE_SRC_DIR}/CertStoreType.h
+ ${VCORE_SRC_DIR}/CRL.h
+ ${VCORE_SRC_DIR}/CRLCacheInterface.h
+ ${VCORE_SRC_DIR}/CryptoHash.h
+ ${VCORE_SRC_DIR}/DeveloperModeValidator.h
+ ${VCORE_SRC_DIR}/IAbstractResponseCache.h
+ ${VCORE_SRC_DIR}/OCSP.h
+ ${VCORE_SRC_DIR}/OCSPCertMgrUtil.h
+ ${VCORE_SRC_DIR}/ParserSchema.h
+ ${VCORE_SRC_DIR}/ReferenceValidator.h
+ ${VCORE_SRC_DIR}/SaxReader.h
+ ${VCORE_SRC_DIR}/SignatureData.h
+ ${VCORE_SRC_DIR}/SignatureFinder.h
+ ${VCORE_SRC_DIR}/SignatureReader.h
+ ${VCORE_SRC_DIR}/WrtSignatureValidator.h
+ ${VCORE_SRC_DIR}/VerificationStatus.h
+ ${VCORE_SRC_DIR}/VCore.h
+ DESTINATION ${INCLUDEDIR}/cert-svc/vcore
+ )
+
+INSTALL(FILES
+ ${VCORE_DIR}/src/cert-svc/ccert.h
+ ${VCORE_DIR}/src/cert-svc/ccrl.h
+ ${VCORE_DIR}/src/cert-svc/cinstance.h
+ ${VCORE_DIR}/src/cert-svc/cerror.h
+ ${VCORE_DIR}/src/cert-svc/cocsp.h
+ ${VCORE_DIR}/src/cert-svc/cpkcs12.h
+ ${VCORE_DIR}/src/cert-svc/cprimitives.h
+ ${VCORE_DIR}/src/cert-svc/cstring.h
+ DESTINATION ${INCLUDEDIR}/cert-svc/cert-svc
+ )
+
+#FILE(MAKE_DIRECTORY /opt/share/cert-svc/pkcs12)
--- /dev/null
+/**
+ * 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 ccert.h
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief This is part of C api for ValidationCore.
+ */
+#ifndef _CERTSVC_CCERT_H_
+#define _CERTSVC_CCERT_H_
+
+#include <time.h>
+
+#include <cert-svc/cinstance.h>
+#include <cert-svc/cstring.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct CertSvcCertificate_t {
+ int privateHandler;
+ CertSvcInstance privateInstance;
+} CertSvcCertificate;
+
+typedef struct CertSvcCertificateList_t {
+ int privateHandler;
+ CertSvcInstance privateInstance;
+} CertSvcCertificateList;
+
+typedef enum CertSvcCertificateForm_t {
+/* CERTSVC_FORM_PEM, */
+ CERTSVC_FORM_DER,
+ CERTSVC_FORM_DER_BASE64
+} CertSvcCertificateForm;
+
+typedef enum CertSvcCertificateField_t {
+ CERTSVC_SUBJECT,
+ CERTSVC_SUBJECT_COMMON_NAME,
+ CERTSVC_SUBJECT_COUNTRY_NAME,
+ CERTSVC_SUBJECT_STATE_NAME,
+ CERTSVC_SUBJECT_ORGANIZATION_NAME,
+ CERTSVC_SUBJECT_ORGANIZATION_UNIT_NAME,
+ CERTSVC_SUBJECT_EMAIL_ADDRESS,
+ CERTSVC_ISSUER,
+ CERTSVC_ISSUER_COMMON_NAME,
+ CERTSVC_ISSUER_COUNTRY_NAME,
+ CERTSVC_ISSUER_STATE_NAME,
+ CERTSVC_ISSUER_ORGANIZATION_NAME,
+ CERTSVC_ISSUER_ORGANIZATION_UNIT_NAME,
+ CERTSVC_VERSION,
+ CERTSVC_SERIAL_NUMBER,
+ CERTSVC_KEY_USAGE,
+ CERTSVC_KEY,
+ CERTSVC_SIGNATURE_ALGORITHM
+} CertSvcCertificateField;
+
+/**
+ * Read certificate from file. Certificate must be in PEM/CER/DER format.
+ *
+ * @param[in] instance CertSvcInstance object.
+ * @param[in] location Path to file with certificate file.
+ * @param[out] certificate Certificate id assigned to loaded certificate.
+ * @return CERTSVC_SUCCESS, CERTSVC_BAD_ALLOC, CERTSVC_FAIL, CERTSVC_WRONG_ARGUMENT
+ */
+int certsvc_certificate_new_from_file(CertSvcInstance instance,
+ const char *location,
+ CertSvcCertificate *certificate);
+
+/**
+ * Read certificate stored in memory.
+ *
+ * @param[in] instance CertSvcInstance object.
+ * @param[in] memory Pointer to memory with certificate data.
+ * @param[in] len Size of certificate.
+ * @param[in] form Certificate format.
+ * @param[out] certificate Certificate id assigned to loaded certificate.
+ * @return CERTSVC_SUCCESS, CERTSVC_BAD_ALLOC, CERTSVC_FAIL
+ */
+int certsvc_certificate_new_from_memory(CertSvcInstance instance,
+ const unsigned char *memory,
+ int len,
+ CertSvcCertificateForm form,
+ CertSvcCertificate *certificate);
+
+/**
+ * Free structures connected with certificate.
+ *
+ * @param[in] certificate Certificate id.
+ */
+void certsvc_certificate_free(CertSvcCertificate certificate);
+
+/**
+ * Save certificate to file. It saves certificate in DER format.
+ *
+ * @param[in] certificate Certificate id.
+ * @param[in] location Path to file.
+ * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_WRONG_ARGUMENT
+ */
+int certsvc_certificate_save_file(CertSvcCertificate certificate, const char *location);
+
+/**
+ * Search certificate with specific data. Result is stored in CertSvcInstance.
+ * This function will erase all preverious results stored in CertSvcInstance but
+ * it will not erase any CertSvcCertificate.
+ *
+ * You can search by fields: CERTSVC_SUBJECT, CERTSVC_ISSUER, CERTSVC_SUBJECT_COMMON_NAME
+ *
+ * @param[in] instance CertSvcInstance object.
+ * @param[in] field Certificate filed name.
+ * @param[in] value Value to search for.
+ * @param[out] handler Handler to search result.
+ * @return CERTSVC_SUCCESS, CERTSVC_BAD_ALLOC, CERTSVC_FAIL, CERTSVC_WRONG_ARGUMENT
+ */
+int certsvc_certificate_search(CertSvcInstance instance,
+ CertSvcCertificateField field,
+ const char *value,
+ CertSvcCertificateList *handler);
+
+/**
+ * This function will return certificate id founded by certsvc_certificate_search.
+ * You can call this function multiple times to get all results.
+ *
+ * @param[in] hadler Hander to search results.
+ * @param[in] position
+ * @param[out] certificate Certficate id.
+ * @return CERTSVC_SUCCESS, CERTSVC_WRONG_ARGUMENT
+ */
+int certsvc_certificate_list_get_one(CertSvcCertificateList handler,
+ int position,
+ CertSvcCertificate *certificate);
+
+/**
+ * Return number of elements on the list.
+ *
+ * @param[in] handler Handler to certifiacte list.
+ * @param[out] length Size of list.
+ * @return CERTSVC_SUCCESS, CERTSVC_WRONG_ARGUMENT
+ */
+int certsvc_certificate_list_get_length(CertSvcCertificateList handler,
+ int *size);
+
+/**
+ * This function will free list. It will not free certificates on the list.
+ * You may free each certificate with certsvc_certificate_free.
+ *
+ * @param[in] handler Handler to search result.
+ */
+void certsvc_certificate_list_free(CertSvcCertificateList handler);
+
+/**
+ * Compare parent certificate subject with child issuer field.
+ *
+ * @param[in] child
+ * @param[in] parent
+ * @param[out] status CERTSVC_TRUE if "signer" was used to sign "child" certificate in other cases it will return CERTSVC_FALSE.
+ * @return CERTSVC_SUCCESS, CERTSVC_WRONG_ARGUMENT
+ */
+int certsvc_certificate_is_signed_by(CertSvcCertificate child,
+ CertSvcCertificate parent,
+ int *status);
+
+/**
+ * Extract specific data from certificate. Data in buffer could be free
+ * by certsvc_free_string function or by
+ * certsvc_instance_free or vcore_instance_reset.
+ *
+ * @param[in] certificate Certificate id.
+ * @param[in] field Type of data to extract.
+ * @param[out] buffer Extracted data.
+ * return CERTSVC_SUCCESS, CERTSVC_BAD_ALLOC, CERTSVC_FAIL
+ */
+int certsvc_certificate_get_string_field(CertSvcCertificate certificate,
+ CertSvcCertificateField field,
+ CertSvcString *buffer);
+
+/**
+ * Extract NOT AFTER data from certificate.
+ *
+ * @param[in] certificate Certificate id.
+ * @param[out] result date
+ * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_WRONG_ARGUMENT
+ */
+int certsvc_certificate_get_not_after(CertSvcCertificate certificate, time_t *result);
+
+/**
+ * Extract NOT AFTER data from certificate.
+ *
+ * @param[in] certificate Certificate id.
+ * @param[out] result date
+ * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_WRONG_ARGUMENT
+ */
+int certsvc_certificate_get_not_before(CertSvcCertificate certificate, time_t *result);
+
+/**
+ * Check certificate. This fuction compares SUBJECT and ISSUER fields.
+ * TODO: This fuction should also check ROOTCA field in certificate.
+ *
+ * @param[in] certificate Certificate id.
+ * @param[out] status CERTSVC_TRUE or CERTSVC_FALSE
+ * @return CERTSVC_SUCCESS, CERTSVC_WRONG_ARGUMENT
+ */
+int certsvc_certificate_is_root_ca(CertSvcCertificate certificate, int *status);
+
+/**
+ * Extract all distribution point from certificate.
+ *
+ * @param[in] certificate Certificate with distribution points.
+ * @param[out] hander Handler to set of string.
+ * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_WRONG_ARGUMENT
+ *
+ * Usage example:
+ *
+ * int max;
+ * CertSvcStringList handler;
+ * certsvc_certificate_get_crl_distribution_points(instance, some_certificate, &handler);
+ * certsvc_certificate_list_get_length(handler, &max);
+ * for(int i=0; i<max; ++i)
+ * char *buffer;
+ * int len;
+ * CertSvcString string;
+ * certsvc_string_list_get_one(handler, i, &string);
+ * printf("%s\n", buffer);
+ * certsvc_string_free(buffer); // optional
+ * }
+ * certsvc_string_list_free(handler); // optional
+ */
+int certsvc_certificate_get_crl_distribution_points(CertSvcCertificate certificate,
+ CertSvcStringList *handler);
+
+/**
+ * Sort certificates chain. This fuction modifies certificate_array.
+ *
+ * If function success:
+ * * certificate array will contain end entity certificate as first element
+ * * last element on the certificate_array will contain Root CA certificate or
+ * CA certificate (if Root CA is not present).
+ *
+ * @param[in/out] certificate_array
+ * @param[in] size Size of certificate_array
+ * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_WRONG_ARGUMENT, CERTSVC_BAD_ALLOC
+ */
+int certsvc_certificate_chain_sort(CertSvcCertificate *unsortedChain, int size);
+
+/**
+ * Base64 string will be connected with same instance as message.
+ * You can free base64 string with certsvc_string_free (or certsvc_instance_reset).
+ *
+ * @param[in] message Buffer with input data.
+ * @param[out] base64 Buffer with output data.
+ * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_WRONG_ARGUMENT
+ */
+int certsvc_base64_encode(CertSvcString message, CertSvcString *base64);
+
+/**
+ * Message string will be connected with same certsvc instance as base64.
+ * You can free base64 string with certsvc_string_free (or certsvc_instance_reset).
+ *
+ * @param[in] base64 Buffer with input data.
+ * @param[out] message Buffer with output data.
+ * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_WRONG_ARGUMENT
+ */
+int certsvc_base64_decode(CertSvcString base64, CertSvcString *message);
+
+/**
+ * Use certificate to verify message.
+ *
+ * @param[in] certificate
+ * @param[in] message
+ * @param[in] algorithm May be set to NULL.
+ * @param[out] status Will be set only if function return CERTSVC_SUCCESS.
+ * It could be set to: CERTSVC_SUCCESS, CERTSVC_INVALID_SIGNATURE
+ * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_WRONG_ARGUMENT, CERTSVC_INVALID_ALGORITHM
+ */
+int certsvc_message_verify(
+ CertSvcCertificate certificate,
+ CertSvcString message,
+ CertSvcString signature,
+ const char *algorithm,
+ int *status);
+
+/**
+ * This function will create full chain and verify in.
+ *
+ * First argument of function will be treatet as endentity certificate.
+ *
+ * This function will success if root CA certificate is stored in
+ * trusted array.
+ *
+ * @param[in] certificate Certificate to verify.
+ * @param[in] trusted Array with trusted certificates.
+ * @param[in] trustedSize Number of trusted certificates in array.
+ * @param[in] untrusted Array with untrusted certificates.
+ * @param[in] untrustedSize Number of untrusted certificate in array.
+ * @param[out] status Will be set only if function return CERTSVC_SUCCESS.
+ * It could be set to: CERTSVC_SUCCESS, CERTSVC_FAIL
+ * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_WRONG_ARGUMENT
+ */
+int certsvc_certificate_verify(
+ CertSvcCertificate certificate,
+ CertSvcCertificate *trusted,
+ int trustedSize,
+ CertSvcCertificate *untrusted,
+ int untrustedSize,
+ int *status);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
--- /dev/null
+/**
+ * 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 ccrl.h
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief This is part of C api for ValidationCore.
+ */
+#ifndef _CERTSVC_CCRL_H_
+#define _CERTSVC_CCRL_H_
+
+#include <time.h>
+
+#include <cert-svc/ccert.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CERTSVC_CRL_GOOD (1<<0)
+#define CERTSVC_CRL_REVOKED (1<<1)
+#define CERTSVC_CRL_VERIFICATION_ERROR (1<<3)
+#define CERTSVC_CRL_NO_SUPPORT (1<<4)
+
+typedef void (*CertSvcCrlCacheWrite)(
+ const char *distributionPoint,
+ const char *body,
+ int bodySize,
+ time_t nextUpdateTime,
+ void *userParam);
+
+typedef int (*CertSvcCrlCacheRead)(
+ const char *distributionPoint,
+ char **body,
+ int *bodySize,
+ time_t *nextUpdateTime,
+ void *userParam);
+
+typedef void (*CertSvcCrlFree)(
+ char *buffer,
+ void *userParam);
+
+void certsvc_crl_cache_functions(
+ CertSvcInstance instance,
+ CertSvcCrlCacheWrite writePtr,
+ CertSvcCrlCacheRead readPtr,
+ CertSvcCrlFree freePtr);
+
+int certsvc_crl_check(
+ CertSvcCertificate certificate,
+ CertSvcCertificate *trustedStore,
+ int storeSize,
+ int force,
+ int *status,
+ void *userParam);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
--- /dev/null
+/**
+ * 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 cerror.h
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief This is part of C api for ValidationCore.
+ */
+
+#ifndef _CERTSVC_CERROR_H_
+#define _CERTSVC_CERROR_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CERTSVC_TRUE (1)
+#define CERTSVC_FALSE (0)
+
+#define CERTSVC_SUCCESS (1)
+#define CERTSVC_FAIL (0) /* Openssl internal error. */
+#define CERTSVC_BAD_ALLOC (-2) /* Memmory allcation error. */
+//#define CERTSVC_FILE_NOT_FOUND (-3) /* Certificate file does not exists. */
+#define CERTSVC_WRONG_ARGUMENT (-4) /* Function argumnet is wrong. */
+#define CERTSVC_INVALID_ALGORITHM (-5) /* Algorithm is not supported. */
+#define CERTSVC_INVALID_SIGNATURE (-6) /* Signature and message does not match. */
+#define CERTSVC_IO_ERROR (-7) /* Certificate file IO error. */
+#define CERTSVC_INVALID_PASSWORD (-8) /* Certificate container password mismatch. */
+#define CERTSVC_DUPLICATED_ALIAS (-9) /* User-provided alias is aleady taken. */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _CERTSVC_CERROR_H_
--- /dev/null
+/**
+ * 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 cinstance.h
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief This is part of C api for ValidationCore.
+ */
+#ifndef _CERTSVC_CINSTANCE_H_
+#define _CERTSVC_CINSTANCE_H_
+
+#include <cert-svc/cerror.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct CertSvcInstance_t {
+ void *privatePtr;
+} CertSvcInstance;
+
+/**
+ * Allocate internal data of CertSvc library and put it in the CertSvcInstance structure.
+ * Initialize Openssl interanal structures, initialize all structures required by libsoup
+ * (libsoup is used by ocps and crl functions).
+ *
+ * @param[out] instance Pointer to CertSvcInstance.
+ * @return CERTSVC_SUCCESS or CERTSVC_FAIL.
+ */
+int certsvc_instance_new(CertSvcInstance *instance);
+
+/**
+ * This function will free all allocated data. All certificate identificator will
+ * be released and all strings allocated by certsvc_certificate_get_string field will be
+ * released also.
+ *
+ * This fucntion does not release CertSvcInstnace!
+ *
+ * Plese note: It is safe to use this function after use certsvc_string_free.
+ *
+ * @param[in] instance CertSvcInstance object.
+ */
+void certsvc_instance_reset(CertSvcInstance instance);
+
+/**
+ * This function will free all allocated data. All certificate identificator will
+ * be released and all strings allocated by certsvc_certificate_get_string field will be
+ * released also.
+ *
+ * This fucntion also release CertSvcInstnace!
+ *
+ * Please note: It is safe use this function after use certsvc_string_free.
+ *
+ * @param[in] instance CertSvcInstance object
+ */
+void certsvc_instance_free(CertSvcInstance instance);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _CERTSVC_CINSTANCE_H_
+
--- /dev/null
+/**
+ * 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 cocsp.h
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief This is C api for ValidationCore.
+ */
+#ifndef _CERTSVC_OCSP_C_API_H_
+#define _CERTSVC_OCSP_C_API_H_
+
+#include <time.h>
+
+#include <cert-svc/ccert.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CERTSVC_OCSP_GOOD (1<<0)
+#define CERTSVC_OCSP_REVOKED (1<<1)
+#define CERTSVC_OCSP_UNKNOWN (1<<2)
+#define CERTSVC_OCSP_VERIFICATION_ERROR (1<<3)
+#define CERTSVC_OCSP_NO_SUPPORT (1<<4)
+#define CERTSVC_OCSP_ERROR (1<<5)
+
+/**
+ * Implementation of ocsp call.
+ *
+ * Please note: to verify certificate you need certificate and his parrent.
+ * This function will always verify chain_size-1 certificates from the chain.
+ *
+ * @param[in] chain Certificate to check.
+ * @param[in] chain_size Size of certificate_array
+ * @param[in] trusted Store with trusted certificates (additional certificates
+ * that may by reqired during verification process).
+ * @param[in] trusted_size Size of trusted certificate store.
+ * @param[in] url Force OCSP to use specific server. Pass NULL to use OCSP server defined in certificate.
+ * @param[out] status Bit field with description of chain validation.
+ * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_WRONG_ARGUMENT
+ */
+int certsvc_ocsp_check(CertSvcCertificate *chain,
+ int chainSize,
+ CertSvcCertificate *trusted,
+ int truestedSize,
+ const char *url,
+ int *status);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/**
+ * 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 cpkcs12.h
+ * @author Jacek Migacz (j.migacz@samsung.com)
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @brief This is part of C api for PKCS#12/PFX storage routines.
+ */
+#ifndef _CERTSVC_CPKCS12_H_
+#define _CERTSVC_CPKCS12_H_
+
+#include <cert-svc/cinstance.h>
+#include <cert-svc/cstring.h>
+#include <cert-svc/ccert.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Query PKCS#12 storage to find out whenever new alias proposal is unique.
+ *
+ * @param[in] instance CertSvcInstance object.
+ * @param[in] proposal Desired alias name.
+ * @param[out] is_unique CERTSVC_TRUE (if there isn't such alias already) or CERTSVC_FALSE.
+ * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_WRONG_ARGUMENT
+ */
+int certsvc_pkcs12_alias_exists(CertSvcInstance instance,
+ CertSvcString alias,
+ int *is_unique);
+
+/**
+ * Import PKCS#12 container from file.
+ *
+ * @param[in] instance CertSvcInstance object.
+ * @param[in] path Path to container file.
+ * @param[in] password Container password (can be empty or NULL).
+ * @param[in] alias Logical name for certificate bundle idenification (can't be empty).
+ * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_IO_ERROR, CERTSVC_INVALID_PASSWORD, CERTSVC_WRONG_ARGUMENT, CERTSVC_DUPLICATED_ALIAS
+ */
+int certsvc_pkcs12_import_from_file(CertSvcInstance instance,
+ CertSvcString path,
+ CertSvcString password,
+ CertSvcString alias);
+
+/**
+ * Get a list of PKCS#12 bundles from storage. This list could be freed by:
+ * certsvc_string_list_free, certsvc_instance_reset, certsvc_instance_free.
+ *
+ * @param[in] instance CertSvcInstance object.
+ * @param[out] pfxIdStringList List of PKCS#12 aliases.
+ * @return CERTSVC_SUCCESS, CERTSVC_BAD_ALLOC, CERTSVC_FAIL
+ */
+int certsvc_pkcs12_get_id_list(CertSvcInstance instance,
+ CertSvcStringList *pfxIdStringList);
+
+/**
+ * Check whenever PKCS#12 container is password protected.
+ *
+ * @param[in] instance CertSvcInstance object.
+ * @param[in] path Path to container file.
+ * @param[out] has_password CERTSVC_TRUE (if container is password protected) or CERTSVC_FALSE.
+ * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_IO_ERROR, CERTSVC_WRONG_ARGUMENT
+ */
+int certsvc_pkcs12_has_password(CertSvcInstance instance,
+ CertSvcString filepath,
+ int *has_password);
+
+/**
+ * Get a list of certificates from PKCS#12 bundle. You may free this list by:
+ * certsvc_certificate_list_free. You may free certificates from list with:
+ * certsvc_certificate_free.
+ *
+ * @param[in] instance CertSvcInstance object.
+ * @param[in] pfxIdString Identification of pfx/pkcs file.
+ * @param[out] certificateList List of certificates.
+ * @return CERTSVC_SUCCESS, CERTSVC_BAD_ALLOC, CERTSVC_FAIL, CERTSVC_IO_ERROR
+ */
+int certsvc_pkcs12_load_certificate_list(CertSvcInstance instance,
+ CertSvcString alias,
+ CertSvcCertificateList* certificateList);
+
+/**
+ * This function will load to memory private file content. This functin will
+ * not parse it in any way.
+ * This memory must be freed by certsvc_private_key_free.
+ *
+ * @param[in] instance CertSvcInstance object.
+ * @param[in] prfIdString Container bundle identifier.
+ * @param[out] buffer Poiner to newly-allocated memory with private key data.
+ * @param[out] size Size of the newly-allocated buffer. Zero means there is no key.
+ * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_IO_ERROR, CERTSVC_WRONG_ARGUMENT
+ */
+int certsvc_pkcs12_private_key_dup(CertSvcInstance instance,
+ CertSvcString alias,
+ char **buffer,
+ size_t *size);
+
+/**
+ * Couter-routine for certsvc_pkcs12_private_key_dup.
+ *
+ * @param[in] pointer Memory claimed by private key.
+ */
+void certsvc_pkcs12_private_key_free(char *buffer);
+
+/**
+ * Remove logical PKCS#12 container with associated certificates and private key.
+ *
+ * @param[in] instance CertSvcInstance object.
+ * @param[in] alias Container bundle identifier.
+ * @return CERTSVC_SUCCESS, CERTSVC_IO_ERROR, CERTSVC_BAD_ALLOC
+ */
+int certsvc_pkcs12_delete(CertSvcInstance instance,
+ CertSvcString alias);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/**
+ * 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 vcore_api_extension.h
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief This is C api for ValidationCore.
+ */
+#ifndef _CERTSVC_C_API_EXTENDED_H_
+#define _CERTSVC_C_API_EXTENDED_H_
+
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+
+#include <cert-svc/ccert.h>
+#include <cert-svc/cstring.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * This will return pointer to X509 base openssl struct. This struct must be release by function
+ * certsvc_certificate_free_x509.
+ *
+ * vcore_instance_free or vcore_instance_reset will not free memory allocated by this function!
+ *
+ * @param[in] certificate Pointer to certificate.
+ * @param[out] cert Duplicate of certificate.
+ * @return CERTSVC_SUCCESS, CERTSVC_WRONG_ARGUMENT, CERTSVC_FAIL
+ */
+int certsvc_certificate_dup_x509(CertSvcCertificate certificate, X509** cert);
+
+/**
+ * Release X509 struct allocated by certsvc_certificate_new_x509_copy function.
+ *
+ * @param[in] x509_copy Pointer to openssl struct.
+ */
+void certsvc_certificate_free_x509(X509 *x509_copy);
+
+/**
+ * This will return pointer to EVP_PKEY base openssl struct. This struct must
+ * be release with function certsvc_pkcs12_free_evp_pkey
+ *
+ * @param[in] instance
+ * @param[in] alias Pkcs12 identificator.
+ * @param[out] pkey Duplicate of private key.
+ * @return CERTSVC_SUCCESS, CERT_FAIL
+ */
+
+int certsvc_pkcs12_dup_evp_pkey(CertSvcInstance instance,
+ CertSvcString alias,
+ EVP_PKEY** pkey);
+
+void certsvc_pkcs12_free_evp_pkey(EVP_PKEY* pkey);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/**
+ * 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 cstring.h
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief This is part of C api for ValidationCore.
+ */
+#ifndef _CERTSVC_CSTRING_H_
+#define _CERTSVC_CSTRING_H_
+
+#include <cert-svc/cinstance.h>
+#include <cert-svc/cstring.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct CertSvcStringList_t {
+ int privateHandler;
+ CertSvcInstance privateInstance;
+} CertSvcStringList;
+
+typedef struct CertSvcString_t {
+ /*
+ * You are not allowed to use private fields of this structure. It is internal
+ * implementation of strings and it may change at any time without notice!
+ * To extract data use certsvc_string_to_cstring function!
+ */
+ char* privateHandler;
+ int privateLength;
+ CertSvcInstance privateInstance;
+} CertSvcString;
+
+/**
+ * This function will duplicate input data. Data in ouput string will be managed by certsvc.
+ *
+ * @param[in] instance CertSvcString will be conected with this instance.
+ * @param[in] input Input data.
+ * @param[in] size Input buffer size.
+ * @param[out] output Buffer with output data.
+ * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_WRONG_ARGUMENT
+ */
+int certsvc_string_new(
+ CertSvcInstance instance,
+ const char *input,
+ int size,
+ CertSvcString *output);
+
+/**
+ * This function wont duplicate input data. Output param will contain pointer to input
+ * so input could not be free as long as ouput param is used.
+ *
+ * @param[in] instance CertSvcString will be conected with this instance.
+ * @param[in] input Input data.
+ * @param[in] size Input buffer size.
+ * @param[out] output Buffer with output data.
+ * @return CERTSVC_SUCCESS, CERTSVC_WRONG_ARGUMENT
+ */
+int certsvc_string_not_managed(
+ CertSvcInstance instance,
+ const char *input,
+ int size,
+ CertSvcString *output);
+
+/**
+ * Extract next result from result set. Function certsvc_string_list_free
+ * does not free results returned by this function. CertSvcString is valid
+ * until certsvc_string_free or vcore_instance_reset or vcore_instance_free
+ * is called.
+ *
+ * @param[in] handler Handler to set of strings.
+ * @param[out] buffer The buffer will be pointing to string with distrubution point url or will be set to NULL if error occures.
+ * @param[out] size Size of data pointed by buffer or 0 if error occures.
+ * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_WRONG_ARGUMENT, CERTSVC_BAD_ALLOC
+ */
+int certsvc_string_list_get_one(CertSvcStringList hander,
+ int position,
+ CertSvcString *buffer);
+
+/**
+ * Extract CertSvcStringList size.
+ *
+ * @param[in] handler Handler to string list.
+ * @param[out] size Number of elements on the list.
+ * @return CERTSVC_SUCCESS, CERTSVC_WRONG_ARGUMENT
+ */
+int certsvc_string_list_get_length(CertSvcStringList hander,int *size);
+
+/**
+ * Free data.
+ *
+ * @param[in] string Data allocated by certsvc_certificate_get_string_field
+ */
+void certsvc_string_free(CertSvcString string);
+
+/**
+ * Free string list.
+ *
+ * Note: This function does not free strings returned by certsvc_string_list_get_one_result.
+ *
+ * @param[in] handler String set handler.
+ */
+void certsvc_string_list_free(CertSvcStringList handler);
+
+/**
+ * Convert CertSvcStringPtr into pure c pointer. Please note that this pointer is valid as long as CertSvcString is valid.
+ *
+ * @param[in] string CertSvcStringPtr.
+ * @param[out] buffer cstring
+ * @param[out] len Length of cstring
+ */
+void certsvc_string_to_cstring(CertSvcString string, const char **buffer, int *len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
--- /dev/null
+Scripts required to create vcoredatabase.
--- /dev/null
+#!/bin/sh
+CHECKSUM=`cat ${2} ${3} 2>/dev/null | md5sum 2>/dev/null | cut -d\ -f1 2>/dev/null`
+echo "#define DB_CHECKSUM DB_VERSION_${CHECKSUM}" > ${1}
+echo "#define DB_CHECKSUM_STR \"DB_VERSION_${CHECKSUM}\"" >> ${1}
+
--- /dev/null
+/*
+ * 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.
+ */
+
+#ifndef ORM_GENERATOR_VCORE_H
+#define ORM_GENERATOR_VCORE_H
+
+#define ORM_GENERATOR_DATABASE_NAME vcore_db_definitions
+#include <dpl/db/orm_generator.h>
+#undef ORM_GENERATOR_DATABASE_NAME
+
+#endif // ORM_GENERATOR_VCORE_H
--- /dev/null
+SQL(
+ PRAGMA foreign_keys = ON;
+ BEGIN TRANSACTION;
+)
+CREATE_TABLE(OCSPResponseStorage)
+ COLUMN_NOT_NULL(cert_chain, TEXT,)
+ COLUMN(end_entity_check, INT,)
+ COLUMN(ocsp_status, INT,)
+ COLUMN(next_update_time, BIGINT,)
+ TABLE_CONSTRAINTS(
+ PRIMARY KEY(cert_chain, end_entity_check)
+ )
+CREATE_TABLE_END()
+
+CREATE_TABLE(CRLResponseStorage)
+ COLUMN_NOT_NULL(distribution_point,TEXT, primary key)
+ COLUMN_NOT_NULL(crl_body, TEXT,)
+ COLUMN(next_update_time, BIGINT,)
+CREATE_TABLE_END()
+
+SQL(
+ COMMIT;
+)
--- /dev/null
+DATABASE_START(vcore)
+
+#include "vcore_db"
+#include "version_db"
+
+DATABASE_END()
--- /dev/null
+/*
+ * 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.
+ */
+
+//Do not include this file directly! It is used only for SQL code generation.
+
+#include <dpl/db/orm_macros.h>
+
+#include "vcore_db_definitions"
--- /dev/null
+SQL(
+ BEGIN TRANSACTION;
+ CREATE TABLE DB_CHECKSUM (version INT);
+ COMMIT;
+)
--- /dev/null
+/*
+ * 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.
+ */
+#include <algorithm>
+#include <string>
+#include <string.h>
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+#include <openssl/buffer.h>
+
+#include <dpl/log/log.h>
+#include <dpl/scoped_free.h>
+
+#include <vcore/Base64.h>
+
+namespace ValidationCore {
+Base64Encoder::Base64Encoder() :
+ m_b64(0),
+ m_bmem(0),
+ m_finalized(false)
+{
+}
+
+void Base64Encoder::append(const std::string &data)
+{
+ if (m_finalized) {
+ LogWarning("Already finalized.");
+ ThrowMsg(Exception::AlreadyFinalized, "Already finalized");
+ }
+
+ if (!m_b64) {
+ reset();
+ }
+ BIO_write(m_b64, data.c_str(), data.size());
+}
+
+void Base64Encoder::finalize()
+{
+ if (m_finalized) {
+ LogWarning("Already finalized.");
+ ThrowMsg(Exception::AlreadyFinalized, "Already finalized.");
+ }
+ m_finalized = true;
+ BIO_flush(m_b64);
+}
+
+std::string Base64Encoder::get()
+{
+ if (!m_finalized) {
+ LogWarning("Not finalized");
+ ThrowMsg(Exception::NotFinalized, "Not finalized");
+ }
+ BUF_MEM *bptr = 0;
+ BIO_get_mem_ptr(m_b64, &bptr);
+ if (bptr == 0) {
+ LogError("Bio internal error");
+ ThrowMsg(Exception::InternalError, "Bio internal error");
+ }
+
+ if (bptr->length > 0) {
+ return std::string(bptr->data, bptr->length);
+ }
+ return std::string();
+}
+
+void Base64Encoder::reset()
+{
+ m_finalized = false;
+ BIO_free_all(m_b64);
+ m_b64 = BIO_new(BIO_f_base64());
+ BIO_set_flags(m_b64, BIO_FLAGS_BASE64_NO_NL);
+ m_bmem = BIO_new(BIO_s_mem());
+ if (!m_b64 || !m_bmem) {
+ LogError("Error during allocation memory in BIO");
+ ThrowMsg(Exception::InternalError,
+ "Error during allocation memory in BIO");
+ }
+ m_b64 = BIO_push(m_b64, m_bmem);
+}
+
+Base64Encoder::~Base64Encoder()
+{
+ BIO_free_all(m_b64);
+}
+
+Base64Decoder::Base64Decoder() :
+ m_finalized(false)
+{
+}
+
+void Base64Decoder::append(const std::string &data)
+{
+ if (m_finalized) {
+ LogWarning("Already finalized.");
+ ThrowMsg(Exception::AlreadyFinalized, "Already finalized.");
+ }
+ m_input.append(data);
+}
+
+static bool whiteCharacter(char a)
+{
+ if (a == '\n') { return true; }
+ return false;
+}
+
+bool Base64Decoder::finalize()
+{
+ if (m_finalized) {
+ LogWarning("Already finalized.");
+ ThrowMsg(Exception::AlreadyFinalized, "Already finalized.");
+ }
+
+ m_finalized = true;
+
+ m_input.erase(std::remove_if(m_input.begin(),
+ m_input.end(),
+ whiteCharacter),
+ m_input.end());
+
+ for (size_t i = 0; i<m_input.size(); ++i) {
+ if (isalnum(m_input[i])
+ || m_input[i] == '+'
+ || m_input[i] == '/'
+ || m_input[i] == '=')
+ {
+ continue;
+ }
+ LogError("Base64 input contains illegal chars: " << m_input[i]);
+ return false;
+ }
+
+ BIO *b64, *bmem;
+ size_t len = m_input.size();
+
+ DPL::ScopedFree<char> buffer(static_cast<char*>(malloc(len)));
+
+ if (!buffer) {
+ LogError("Error in malloc.");
+ ThrowMsg(Exception::InternalError, "Error in malloc.");
+ }
+
+ memset(buffer.Get(), 0, len);
+ b64 = BIO_new(BIO_f_base64());
+ if (!b64) {
+ LogError("Couldn't create BIO object.");
+ ThrowMsg(Exception::InternalError, "Couldn't create BIO object.");
+ }
+ BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
+ DPL::ScopedFree<char> tmp(strdup(m_input.c_str()));
+ m_input.clear();
+
+ bmem = BIO_new_mem_buf(tmp.Get(), len);
+
+ if (!bmem) {
+ BIO_free(b64);
+ LogError("Internal error in BIO");
+ ThrowMsg(Exception::InternalError, "Internal error in BIO");
+ }
+
+ bmem = BIO_push(b64, bmem);
+
+ if (!bmem) {
+ BIO_free(b64);
+ LogError("Internal error in BIO");
+ ThrowMsg(Exception::InternalError, "Internal error in BIO");
+ }
+
+ int readlen = BIO_read(bmem, buffer.Get(), len);
+ m_output.clear();
+
+ bool status = true;
+
+ if (readlen > 0) {
+ m_output.append(buffer.Get(), readlen);
+ } else {
+ status = false;
+ }
+
+ BIO_free_all(bmem);
+ return status;
+}
+
+std::string Base64Decoder::get() const
+{
+ if (!m_finalized) {
+ LogWarning("Not finalized.");
+ ThrowMsg(Exception::NotFinalized, "Not finalized");
+ }
+ return m_output;
+}
+
+void Base64Decoder::reset()
+{
+ m_finalized = false;
+ m_input.clear();
+ m_output.clear();
+}
+} // namespace ValidationCore
--- /dev/null
+/*
+ * 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.
+ */
+#ifndef _BASE64_H_
+#define _BASE64_H_
+
+#include <string>
+#include <dpl/noncopyable.h>
+#include <dpl/exception.h>
+
+struct bio_st;
+typedef bio_st BIO;
+
+namespace ValidationCore {
+class Base64Encoder : public DPL::Noncopyable
+{
+ public:
+ class Exception
+ {
+ public:
+ DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
+ DECLARE_EXCEPTION_TYPE(Base, InternalError)
+ DECLARE_EXCEPTION_TYPE(Base, NotFinalized)
+ DECLARE_EXCEPTION_TYPE(Base, AlreadyFinalized)
+ };
+ Base64Encoder();
+ void append(const std::string &data);
+ void finalize();
+ std::string get();
+ void reset();
+ ~Base64Encoder();
+
+ private:
+ BIO *m_b64;
+ BIO *m_bmem;
+ bool m_finalized;
+};
+
+class Base64Decoder : public DPL::Noncopyable
+{
+ public:
+ class Exception
+ {
+ public:
+ DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
+ DECLARE_EXCEPTION_TYPE(Base, InternalError)
+ DECLARE_EXCEPTION_TYPE(Base, NotFinalized)
+ DECLARE_EXCEPTION_TYPE(Base, AlreadyFinalized)
+ };
+ Base64Decoder();
+ void append(const std::string &data);
+
+ /*
+ * Function will return false when BIO_read fails
+ * (for example: when string was not in base64 format).
+ */
+ bool finalize();
+ std::string get() const;
+ void reset();
+ ~Base64Decoder()
+ {
+ }
+
+ private:
+ std::string m_input;
+ std::string m_output;
+ bool m_finalized;
+};
+} // namespace ValidationCore
+
+#endif
--- /dev/null
+/*
+ * 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.
+ */
+/*!
+ * @author Bartlomiej Grzelewski(b.grzelewski@samsung.com)
+ * @version 0.2
+ * @file CRL.cpp
+ * @brief Routines for certificate validation over CRL
+ */
+
+#include <vcore/CRL.h>
+#include <vcore/CRLImpl.h>
+
+namespace ValidationCore {
+
+CRL::CRL(CRLCacheInterface *ptr)
+ : m_impl(new CRLImpl(ptr))
+{}
+
+CRL::~CRL() {
+ delete m_impl;
+}
+
+CRL::RevocationStatus CRL::checkCertificate(const CertificatePtr &argCert) {
+ return m_impl->checkCertificate(argCert);
+}
+
+CRL::RevocationStatus CRL::checkCertificateChain(
+ CertificateCollection certChain)
+{
+ return m_impl->checkCertificateChain(certChain);
+}
+
+VerificationStatus CRL::checkEndEntity(CertificateCollection &chain) {
+ return m_impl->checkEndEntity(chain);
+}
+
+void CRL::addToStore(const CertificatePtr &argCert) {
+ m_impl->addToStore(argCert);
+}
+
+bool CRL::updateList(const CertificatePtr &argCert,
+ const UpdatePolicy updatePolicy)
+{
+ return m_impl->updateList(argCert, updatePolicy);
+}
+
+void CRL::addToStore(const CertificateCollection &collection) {
+ m_impl->addToStore(collection);
+}
+
+bool CRL::updateList(const CertificateCollection &collection,
+ UpdatePolicy updatePolicy)
+{
+ return m_impl->updateList(collection, updatePolicy);
+}
+
+} // namespace ValidationCore
--- /dev/null
+/*
+ * 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.
+ */
+/*!
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 0.5
+ * @file CRL.h
+ * @brief Routines for certificate validation over CRL
+ */
+
+#ifndef _VALIDATION_CORE_ENGINE_CRL_H_
+#define _VALIDATION_CORE_ENGINE_CRL_H_
+
+#include <list>
+#include <string>
+
+#include <dpl/exception.h>
+#include <dpl/shared_ptr.h>
+#include <dpl/noncopyable.h>
+#include <dpl/log/log.h>
+
+#include <vcore/Certificate.h>
+#include <vcore/CertificateCollection.h>
+#include <vcore/VerificationStatus.h>
+#include <vcore/CRLCacheInterface.h>
+
+namespace ValidationCore {
+
+namespace CRLException {
+DECLARE_EXCEPTION_TYPE(DPL::Exception, CRLException)
+DECLARE_EXCEPTION_TYPE(CRLException, StorageError)
+DECLARE_EXCEPTION_TYPE(CRLException, DownloadFailed)
+DECLARE_EXCEPTION_TYPE(CRLException, InternalError)
+DECLARE_EXCEPTION_TYPE(CRLException, InvalidParameter)
+} // namespace CRLException
+
+class CRLImpl;
+
+class CRL : DPL::Noncopyable
+{
+public:
+ typedef std::list<std::string> StringList;
+
+ enum UpdatePolicy
+ {
+ UPDATE_ON_EXPIRED, /**< Download and update CRL only when next update
+ date has expired */
+ UPDATE_ON_DEMAND /**< Download and update CRL regardless next update
+ date */
+ };
+
+ struct RevocationStatus
+ {
+ bool isCRLValid; /**< True when CRL was valid during
+ certificate validation */
+ bool isRevoked; /**< True when certificate is revoked */
+ };
+
+ CRL(CRLCacheInterface *ptr);
+ virtual ~CRL();
+
+ /**
+ * @brief Checks if given certificate is revoked.
+ *
+ * @details This function doesn't update CRL list. If related CRL
+ * is out of date the #isCRLValid return parameter is set to false.
+ *
+ * @param[in] argCert The certificate to check against revocation.
+ * @return RevocationStatus.isRevoked True when certificate is revoked,
+ * false otherwise.
+ * RevocationStatus.isCRLValid True if related CRL has not expired,
+ * false otherwise.
+ */
+ RevocationStatus checkCertificate(const CertificatePtr &argCert);
+
+ /**
+ * @brief Checks if any certificate from certificate chain is revoked.
+ *
+ * @details This function doesn't update CRL lists. If any of related
+ * CRL is out of date the #isCRLValid parameter is set to true.
+ * This function adds valid certificates from the chain to internal storage
+ * map so they'll be available in further check operations for current
+ * CRL object.
+ *
+ * @param[in] argCert The certificate chain to check against revocation.
+ * @return RevocationStatus.isRevoked True when any from certificate chain
+ * is revoked, false otherwise.
+ * RevocationStatus.isCRLValid True if all of related CRLs has
+ * not expired, false otherwise.
+ */
+ RevocationStatus checkCertificateChain(CertificateCollection certChain);
+
+ VerificationStatus checkEndEntity(CertificateCollection &chain);
+
+ /**
+ * @brief Updates CRL related with given certificate.
+ *
+ * @details This function updates CRL list related with given certificate.
+ * If CRL related with given certificate is not stored in database
+ * then this function will download CRL and store it in database.
+ *
+ * @param[in] argCert The certificate for which the CRL will be updated
+ * @param[in] updatePolicy Determine when CRL will be downloaded and updated
+ * @return True when CRL for given certificate was updated successfully,
+ * false otherwise.
+ */
+ bool updateList(const CertificatePtr &argCert,
+ const UpdatePolicy updatePolicy);
+
+ /**
+ * @brief Updates CRL related with given certificates.
+ *
+ * @details This function updates CRL lists related with given certificates.
+ * If CRL related with given certificate is not stored in database
+ * then this function will download CRL and store it in database.
+ *
+ * @param[in] collection The certificate collection for which the CRL will
+ * be updated
+ * @param[in] updatePolicy Determine when CRL will be downloaded and updated
+ * @return True when CRL for given certificate was updated successfully,
+ * false otherwise.
+ */
+ bool updateList(const CertificateCollection &collection,
+ const UpdatePolicy updatePolisy);
+
+ /**
+ * @brief Add certificates to trusted certificates store.
+ *
+ * @param[in] collection The certificate collection which will be
+ * added to known certificate store.
+ */
+ void addToStore(const CertificateCollection &collection);
+
+ /**
+ * @brief Add one certificate to trusted certificates store.
+ *
+ * @param[in] collection The certificate collection which will be
+ * added to known certificate store.
+ */
+ void addToStore(const CertificatePtr &argCert);
+private:
+ friend class CachedCRL;
+ CRLImpl *m_impl;
+};
+
+} // namespace ValidationCore
+
+#endif // _VALIDATION_CORE_ENGINE_CRL_H_
--- /dev/null
+/*
+ * 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.
+ */
+/*
+ * @author Bartlomiej Grzelewski(b.grzelewski@samsung.com)
+ * @version 0.1
+ * @file CRLCacheDAO.cpp
+ * @brief CRLCacheInterface implementation.
+ */
+
+#include <vcore/CRLCacheDAO.h>
+#include <vcore/CertificateCacheDAO.h>
+
+namespace ValidationCore {
+
+bool CRLCacheDAO::getCRLResponse(CRLCachedData *ptr){
+ return CertificateCacheDAO::getCRLResponse(ptr);
+}
+
+void CRLCacheDAO::setCRLResponse(CRLCachedData *ptr){
+ CertificateCacheDAO::setCRLResponse(ptr);
+}
+
+} // namespace ValidationCore
--- /dev/null
+/*
+ * 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.
+ */
+/*
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 0.1
+ * @file CRLCacheDAO.h
+ * @brief CRLCacheInterface implementation.
+ */
+#ifndef _CRLCACHEDAO_H_
+#define _CRLCACHEDAO_H_
+
+#include <vcore/CRLCacheInterface.h>
+
+namespace ValidationCore {
+
+class CRLCacheDAO : public CRLCacheInterface {
+public:
+ virtual bool getCRLResponse(CRLCachedData *ptr);
+ virtual void setCRLResponse(CRLCachedData *ptr);
+};
+
+} // namespace ValidationCore
+
+#endif
--- /dev/null
+/*
+ * 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.
+ */
+/*!
+ * @author Bartlomiej Grzelewski(b.grzelewski@samsung.com)
+ * @version 0.1
+ * @file CRLCacheInterface.h
+ * @brief CRLCacheInterface definition.
+ */
+#ifndef _CRLCACHEINTERFACE_H_
+#define _CRLCACHEINTERFACE_H_
+
+#include <string>
+
+namespace ValidationCore {
+
+struct CRLCachedData
+{
+ std::string distribution_point;
+ std::string crl_body;
+ time_t next_update_time;
+};
+
+class CRLCacheInterface {
+public:
+ virtual bool getCRLResponse(CRLCachedData *ptr) = 0;
+ virtual void setCRLResponse(CRLCachedData *ptr) = 0;
+};
+
+} // namespace ValidationCore
+
+#endif
--- /dev/null
+/*
+ * 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.
+ */
+/*!
+ * @author Piotr Marcinkiewicz(p.marcinkiew@samsung.com)
+ * @version 0.2
+ * @file CRLImpl.h
+ * @brief Routines for certificate validation over CRL
+ */
+
+#include <vcore/CRL.h>
+#include <vcore/CRLImpl.h>
+
+#include <set>
+#include <algorithm>
+
+#include <openssl/err.h>
+#include <openssl/objects.h>
+#include <openssl/ocsp.h>
+#include <openssl/pem.h>
+#include <openssl/x509v3.h>
+
+#include <dpl/log/log.h>
+#include <dpl/assert.h>
+#include <dpl/exception.h>
+#include <dpl/scoped_ptr.h>
+#include <dpl/scoped_array.h>
+#include <dpl/db/orm.h>
+#include <dpl/foreach.h>
+
+#include <vcore/Base64.h>
+#include <vcore/Certificate.h>
+#include <vcore/SoupMessageSendSync.h>
+#include <vcore/CRLCacheInterface.h>
+
+namespace {
+const char *CRL_LOOKUP_DIR_1 = "/usr/share/cert-svc/ca-certs/code-signing/wac";
+const char *CRL_LOOKUP_DIR_2 = "/opt/share/cert-svc/certs/code-signing/wac";
+} //anonymous namespace
+
+namespace ValidationCore {
+
+CRL::StringList CRLImpl::getCrlUris(const CertificatePtr &argCert)
+{
+ CRL::StringList result = argCert->getCrlUris();
+
+ if (!result.empty()) {
+ return result;
+ }
+ LogInfo("No distribution points found. Getting from CA cert.");
+ X509_STORE_CTX *ctx = createContext(argCert);
+ X509_OBJECT obj;
+
+ //Try to get distribution points from CA certificate
+ int retVal = X509_STORE_get_by_subject(ctx, X509_LU_X509,
+ X509_get_issuer_name(argCert->
+ getX509()),
+ &obj);
+ X509_STORE_CTX_free(ctx);
+ if (0 >= retVal) {
+ LogError("No dedicated CA certificate available");
+ return result;
+ }
+ CertificatePtr caCert(new Certificate(obj.data.x509));
+ X509_OBJECT_free_contents(&obj);
+ return caCert->getCrlUris();
+}
+
+CRLImpl::CRLImpl(CRLCacheInterface *ptr)
+ : m_crlCache(ptr)
+{
+ Assert(m_crlCache != NULL);
+
+ LogInfo("CRL storage initialization.");
+ m_store = X509_STORE_new();
+ if (!m_store) {
+ LogError("Failed to create new store.");
+ ThrowMsg(CRLException::StorageError,
+ "Not possible to create new store.");
+ }
+ m_lookup = X509_STORE_add_lookup(m_store, X509_LOOKUP_hash_dir());
+ if (!m_lookup) {
+ cleanup();
+ LogError("Failed to add hash dir lookup");
+ ThrowMsg(CRLException::StorageError,
+ "Not possible to add hash dir lookup.");
+ }
+ // Add hash dir pathname for CRL checks
+ bool retVal = X509_LOOKUP_add_dir(m_lookup,
+ CRL_LOOKUP_DIR_1, X509_FILETYPE_PEM) == 1;
+ retVal &= retVal && (X509_LOOKUP_add_dir(m_lookup, CRL_LOOKUP_DIR_1,
+ X509_FILETYPE_ASN1) == 1);
+ retVal &= retVal && (X509_LOOKUP_add_dir(m_lookup, CRL_LOOKUP_DIR_2,
+ X509_FILETYPE_PEM) == 1);
+ retVal &= retVal && (X509_LOOKUP_add_dir(m_lookup, CRL_LOOKUP_DIR_2,
+ X509_FILETYPE_ASN1) == 1);
+ if (!retVal) {
+ LogError("Failed to add lookup dir for PEM files.");
+ cleanup();
+ ThrowMsg(CRLException::StorageError,
+ "Failed to add lookup dir for PEM files.");
+ }
+ LogInfo("CRL storage initialization complete.");
+}
+
+CRLImpl::~CRLImpl()
+{
+ cleanup();
+ delete m_crlCache;
+}
+
+void CRLImpl::cleanup()
+{
+ LogInfo("Free CRL storage");
+ // STORE is responsible for LOOKUP release
+ // X509_LOOKUP_free(m_lookup);
+ X509_STORE_free(m_store);
+}
+
+CRL::RevocationStatus CRLImpl::checkCertificate(const CertificatePtr &argCert)
+{
+ CRL::RevocationStatus retStatus = {false, false};
+ int retVal = 0;
+ CRL::StringList crlUris = getCrlUris(argCert);
+ FOREACH(it, crlUris) {
+ CRLDataPtr crl = getCRL(*it);
+ if (!crl) {
+ LogDebug("CRL not found for URI: " << *it);
+ continue;
+ }
+ X509_CRL *crlInternal = convertToInternal(crl);
+
+ //Check date
+ if (X509_CRL_get_nextUpdate(crlInternal)) {
+ retVal = X509_cmp_current_time(
+ X509_CRL_get_nextUpdate(crlInternal));
+ retStatus.isCRLValid = retVal > 0;
+ } else {
+ // If nextUpdate is not set assume it is actual.
+ retStatus.isCRLValid = true;
+ }
+ LogInfo("CRL valid: " << retStatus.isCRLValid);
+ X509_REVOKED rev;
+ rev.serialNumber = X509_get_serialNumber(argCert->getX509());
+ // sk_X509_REVOKED_find returns index if serial number is found on list
+ retVal = sk_X509_REVOKED_find(crlInternal->crl->revoked, &rev);
+ X509_CRL_free(crlInternal);
+ retStatus.isRevoked = retVal != -1;
+ LogInfo("CRL revoked: " << retStatus.isRevoked);
+
+ if (!retStatus.isRevoked && isOutOfDate(crl)) {
+ LogDebug("Certificate is not Revoked, but CRL is outOfDate.");
+ continue;
+ }
+
+ return retStatus;
+ }
+ // If there is no CRL for any of URIs it means it's not possible to
+ // tell anything about revocation status but it's is not an error.
+ return retStatus;
+}
+
+CRL::RevocationStatus CRLImpl::checkCertificateChain(CertificateCollection
+ certChain)
+{
+ if (!certChain.sort()) {
+ LogError("Certificate list doesn't create chain.");
+ ThrowMsg(CRLException::InvalidParameter,
+ "Certificate list doesn't create chain.");
+ }
+
+ CRL::RevocationStatus ret;
+ ret.isCRLValid = true;
+ ret.isRevoked = false;
+ const CertificateList &certList = certChain.getChain();
+ FOREACH(it, certList) {
+ if (!(*it)->isRootCert()) {
+ LogInfo("Certificate common name: " << *((*it)->getCommonName()));
+ CRL::RevocationStatus certResult = checkCertificate(*it);
+ ret.isCRLValid &= certResult.isCRLValid;
+ ret.isRevoked |= certResult.isRevoked;
+ if (ret.isCRLValid && !ret.isRevoked) {
+ addToStore(*it);
+ }
+ if (ret.isRevoked) {
+ return ret;
+ }
+ }
+ }
+ return ret;
+}
+
+VerificationStatus CRLImpl::checkEndEntity(CertificateCollection &chain)
+{
+ if (!chain.sort() && !chain.empty()) {
+ LogInfo("Could not find End Entity certificate. "
+ "Collection does not form chain.");
+ return VERIFICATION_STATUS_ERROR;
+ }
+ CertificateList::const_iterator iter = chain.begin();
+ CRL::RevocationStatus stat = checkCertificate(*iter);
+ if (stat.isRevoked) {
+ return VERIFICATION_STATUS_REVOKED;
+ }
+ if (stat.isCRLValid) {
+ return VERIFICATION_STATUS_GOOD;
+ }
+ return VERIFICATION_STATUS_ERROR;
+}
+
+void CRLImpl::addToStore(const CertificatePtr &argCert)
+{
+ X509_STORE_add_cert(m_store, argCert->getX509());
+}
+
+bool CRLImpl::isOutOfDate(const CRLDataPtr &crl) const {
+ X509_CRL *crlInternal = convertToInternal(crl);
+
+ bool result = false;
+ if (X509_CRL_get_nextUpdate(crlInternal)) {
+ if (0 > X509_cmp_current_time(X509_CRL_get_nextUpdate(crlInternal))) {
+ result = true;
+ } else {
+ result = false;
+ }
+ } else {
+ result = true;
+ }
+ X509_CRL_free(crlInternal);
+ return result;
+}
+
+bool CRLImpl::updateList(const CertificatePtr &argCert,
+ const CRL::UpdatePolicy updatePolicy)
+{
+ LogInfo("Update CRL for certificate");
+
+ // Retrieve distribution points
+ CRL::StringList crlUris = getCrlUris(argCert);
+ FOREACH(it, crlUris) {
+ // Try to get CRL from database
+ LogInfo("Getting CRL for URI: " << *it);
+
+ bool downloaded = false;
+
+ CRLDataPtr crl;
+
+ // If updatePolicy == UPDATE_ON_DEMAND we dont care
+ // about data in cache. New crl must be downloaded.
+ if (updatePolicy == CRL::UPDATE_ON_EXPIRED) {
+ crl = getCRL(*it);
+ }
+
+ if (!!crl && isOutOfDate(crl)) {
+ LogDebug("Crl out of date - downloading.");
+ crl = downloadCRL(*it);
+ downloaded = true;
+ }
+
+ if (!crl) {
+ LogDebug("Crl not found in cache - downloading.");
+ crl = downloadCRL(*it);
+ downloaded = true;
+ }
+
+ if (!crl) {
+ LogDebug("Failed to obtain CRL. URL: " << *it);
+ continue;
+ }
+
+ if (!!crl && isOutOfDate(crl)) {
+ LogError("CRL out of date. Broken URL: " << *it);
+ }
+
+ // Make X509 internal structure
+ X509_CRL *crlInternal = convertToInternal(crl);
+
+ //Check if CRL is signed
+ if (!verifyCRL(crlInternal, argCert)) {
+ LogError("Failed to verify CRL. URI: " << crl->uri);
+ X509_CRL_free(crlInternal);
+ return false;
+ }
+ X509_CRL_free(crlInternal);
+
+ if (downloaded) {
+ updateCRL(crl);
+ }
+ return true;
+ }
+
+ return false;
+}
+
+void CRLImpl::addToStore(const CertificateCollection &collection)
+{
+ FOREACH(it, collection){
+ addToStore(*it);
+ }
+}
+
+bool CRLImpl::updateList(const CertificateCollection &collection,
+ CRL::UpdatePolicy updatePolicy)
+{
+ bool failed = false;
+
+ FOREACH(it, collection){
+ failed |= !updateList(*it, updatePolicy);
+ }
+
+ return !failed;
+}
+
+bool CRLImpl::verifyCRL(X509_CRL *crl,
+ const CertificatePtr &cert)
+{
+ X509_OBJECT obj;
+ X509_STORE_CTX *ctx = createContext(cert);
+
+ /* get issuer certificate */
+ int retVal = X509_STORE_get_by_subject(ctx, X509_LU_X509,
+ X509_CRL_get_issuer(crl), &obj);
+ X509_STORE_CTX_free(ctx);
+ if (0 >= retVal) {
+ LogError("Unknown CRL issuer certificate!");
+ return false;
+ }
+
+ /* extract public key and verify signature */
+ EVP_PKEY *pkey = X509_get_pubkey(obj.data.x509);
+ X509_OBJECT_free_contents(&obj);
+ if (!pkey) {
+ LogError("Failed to get issuer's public key.");
+ return false;
+ }
+ retVal = X509_CRL_verify(crl, pkey);
+ EVP_PKEY_free(pkey);
+ if (0 > retVal) {
+ LogError("Failed to verify CRL.");
+ return false;
+ } else if (0 == retVal) {
+ LogError("CRL is invalid");
+ return false;
+ }
+ LogInfo("CRL is valid.");
+ return true;
+}
+
+bool CRLImpl::isPEMFormat(const CRLDataPtr &crl) const
+{
+ const char *pattern = "-----BEGIN X509 CRL-----";
+ std::string content(crl->buffer, crl->length);
+ if (content.find(pattern) != std::string::npos) {
+ LogInfo("CRL is in PEM format.");
+ return true;
+ }
+ LogInfo("CRL is in DER format.");
+ return false;
+}
+
+X509_CRL *CRLImpl::convertToInternal(const CRLDataPtr &crl) const
+{
+ //At this point it's not clear does crl have DER or PEM format
+ X509_CRL *ret = NULL;
+ if (isPEMFormat(crl)) {
+ BIO *bmem = BIO_new_mem_buf(crl->buffer, crl->length);
+ if (!bmem) {
+ LogError("Failed to allocate memory in BIO");
+ ThrowMsg(CRLException::InternalError,
+ "Failed to allocate memory in BIO");
+ }
+ ret = PEM_read_bio_X509_CRL(bmem, NULL, NULL, NULL);
+ BIO_free_all(bmem);
+ } else {
+ //If it's not PEM it must be DER format
+ std::string content(crl->buffer, crl->length);
+ const unsigned char *buffer =
+ reinterpret_cast<unsigned char*>(crl->buffer);
+ ret = d2i_X509_CRL(NULL, &buffer, crl->length);
+ }
+ if (!ret) {
+ LogError("Failed to convert to internal structure");
+ ThrowMsg(CRLException::InternalError,
+ "Failed to convert to internal structure");
+ }
+ return ret;
+}
+
+X509_STORE_CTX *CRLImpl::createContext(const CertificatePtr &argCert)
+{
+ X509_STORE_CTX *ctx;
+ ctx = X509_STORE_CTX_new();
+ if (!ctx) {
+ ThrowMsg(CRLException::StorageError, "Failed to create new context.");
+ }
+ X509_STORE_CTX_init(ctx, m_store, argCert->getX509(), NULL);
+ return ctx;
+}
+
+CRLImpl::CRLDataPtr CRLImpl::downloadCRL(const std::string &uri)
+{
+ using namespace SoupWrapper;
+
+ char *cport = 0, *chost = 0,*cpath = 0;
+ int use_ssl = 0;
+
+ if (!OCSP_parse_url(const_cast<char*>(uri.c_str()),
+ &chost,
+ &cport,
+ &cpath,
+ &use_ssl))
+ {
+ LogWarning("Error in OCSP_parse_url");
+ return CRLDataPtr();
+ }
+
+ std::string host = chost;
+ if (cport) {
+ host += ":";
+ host += cport;
+ }
+
+ free(cport);
+ free(chost);
+ free(cpath);
+
+ SoupMessageSendSync message;
+ message.setHost(uri);
+ message.setHeader("Host", host);
+
+ if (SoupMessageSendSync::REQUEST_STATUS_OK != message.sendSync()) {
+ LogWarning("Error in sending network request.");
+ return CRLDataPtr();
+ }
+
+ SoupMessageSendBase::MessageBuffer mBuffer = message.getResponse();
+ return CRLDataPtr(new CRLData(mBuffer,uri));
+}
+
+CRLImpl::CRLDataPtr CRLImpl::getCRL(const std::string &uri) const
+{
+ CRLCachedData cachedCrl;
+ cachedCrl.distribution_point = uri;
+ if (!(m_crlCache->getCRLResponse(&cachedCrl))) {
+ LogInfo("CRL not present in database. URI: " << uri);
+ return CRLDataPtr();
+ }
+
+ std::string body = cachedCrl.crl_body;
+
+ LogInfo("CRL found in database.");
+ //TODO: remove when ORM::blob available
+ //Encode buffer to base64 format to store in database
+
+ Base64Decoder decoder;
+ decoder.append(body);
+ if (!decoder.finalize()) {
+ LogError("Failed to decode base64 format.");
+ ThrowMsg(CRLException::StorageError, "Failed to decode base64 format.");
+ }
+ std::string crlBody = decoder.get();
+
+ DPL::ScopedArray<char> bodyBuffer(new char[crlBody.length()]);
+ crlBody.copy(bodyBuffer.Get(), crlBody.length());
+ return CRLDataPtr(new CRLData(bodyBuffer.Release(), crlBody.length(),
+ uri));
+}
+
+void CRLImpl::updateCRL(const CRLDataPtr &crl)
+{
+ //TODO: remove when ORM::blob available
+ //Encode buffer to base64 format to store in database
+ Base64Encoder encoder;
+ if (!crl || !crl->buffer) {
+ ThrowMsg(CRLException::InternalError, "CRL buffer is empty");
+ }
+ encoder.append(std::string(crl->buffer, crl->length));
+ encoder.finalize();
+ std::string b64CRLBody = encoder.get();
+
+ time_t nextUpdateTime = 0;
+ X509_CRL *crlInternal = convertToInternal(crl);
+
+ if (X509_CRL_get_nextUpdate(crlInternal)) {
+ asn1TimeToTimeT(X509_CRL_get_nextUpdate(crlInternal),
+ &nextUpdateTime);
+ }
+
+ X509_CRL_free(crlInternal);
+ //Update/insert crl body
+ CRLCachedData data;
+ data.distribution_point = crl->uri;
+ data.crl_body = b64CRLBody;
+ data.next_update_time = nextUpdateTime;
+
+ m_crlCache->setCRLResponse(&data);
+}
+
+} // namespace ValidationCore
--- /dev/null
+/*
+ * 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.
+ */
+/*!
+ * @author Piotr Marcinkiewicz(p.marcinkiew@samsung.com)
+ * @version 0.4
+ * @file CRLImpl.h
+ * @brief Routines for certificate validation over CRL
+ */
+
+#ifndef _VALIDATION_CORE_ENGINE_CRLIMPL_H_
+#define _VALIDATION_CORE_ENGINE_CRLIMPL_H_
+
+#include <dpl/exception.h>
+#include <dpl/shared_ptr.h>
+#include <dpl/noncopyable.h>
+#include <dpl/log/log.h>
+
+#include <openssl/x509.h>
+
+#include <vcore/CRL.h>
+#include <vcore/Certificate.h>
+#include <vcore/CertificateCollection.h>
+#include <vcore/SoupMessageSendBase.h>
+#include <vcore/VerificationStatus.h>
+#include <vcore/CRLCacheInterface.h>
+#include <vcore/TimeConversion.h>
+
+namespace ValidationCore {
+
+class CRLImpl : DPL::Noncopyable
+{
+ protected:
+ X509_STORE *m_store;
+ X509_LOOKUP *m_lookup;
+ CRLCacheInterface *m_crlCache;
+
+ class CRLData : DPL::Noncopyable
+ {
+ public:
+ //TODO: change to SharedArray when available
+ char *buffer;
+ size_t length;
+ std::string uri;
+
+ CRLData(char* _buffer,
+ size_t _length,
+ const std::string &_uri) :
+ buffer(_buffer),
+ length(_length),
+ uri(_uri)
+ {
+ }
+
+ CRLData(const SoupWrapper::SoupMessageSendBase::MessageBuffer &mBuff,
+ const std::string &mUri)
+ : uri(mUri)
+ {
+ buffer = new char[mBuff.size()];
+ length = mBuff.size();
+ memcpy(buffer, &mBuff[0], mBuff.size());
+ }
+
+ ~CRLData()
+ {
+ LogInfo("Delete buffer");
+ delete[] buffer;
+ }
+ };
+ typedef DPL::SharedPtr<CRLData> CRLDataPtr;
+
+ CRLDataPtr getCRL(const std::string &uri) const;
+ CRLDataPtr downloadCRL(const std::string &uri);
+ X509_STORE_CTX *createContext(const CertificatePtr &argCert);
+ void updateCRL(const CRLDataPtr &crl);
+ X509_CRL *convertToInternal(const CRLDataPtr &crl) const;
+ CRL::StringList getCrlUris(const CertificatePtr &argCert);
+ bool isPEMFormat(const CRLDataPtr &crl) const;
+ bool verifyCRL(X509_CRL *crl,
+ const CertificatePtr &cert);
+ void cleanup();
+ bool isOutOfDate(const CRLDataPtr &crl) const;
+
+ friend class CachedCRL;
+ public:
+ CRLImpl(CRLCacheInterface *ptr);
+ ~CRLImpl();
+
+ /**
+ * @brief Checks if given certificate is revoked.
+ *
+ * @details This function doesn't update CRL list. If related CRL
+ * is out of date the #isCRLValid return parameter is set to false.
+ *
+ * @param[in] argCert The certificate to check against revocation.
+ * @return RevocationStatus.isRevoked True when certificate is revoked,
+ * false otherwise.
+ * RevocationStatus.isCRLValid True if related CRL has not expired,
+ * false otherwise.
+ */
+ CRL::RevocationStatus checkCertificate(const CertificatePtr &argCert);
+
+ /**
+ * @brief Checks if any certificate from certificate chain is revoked.
+ *
+ * @details This function doesn't update CRL lists. If any of related
+ * CRL is out of date the #isCRLValid parameter is set to true.
+ * This function adds valid certificates from the chain to internal storage
+ * map so they'll be available in further check operations for current
+ * CRL object.
+ *
+ * @param[in] argCert The certificate chain to check against revocation.
+ * @return RevocationStatus.isRevoked True when any from certificate chain
+ * is revoked, false otherwise.
+ * RevocationStatus.isCRLValid True if all of related CRLs has
+ * not expired, false otherwise.
+ */
+ CRL::RevocationStatus checkCertificateChain(CertificateCollection certChain);
+
+ VerificationStatus checkEndEntity(CertificateCollection &chain);
+
+ /**
+ * @brief Updates CRL related with given certificate.
+ *
+ * @details This function updates CRL list related with given certificate.
+ * If CRL related with given certificate is not stored in database
+ * then this function will download CRL and store it in database.
+ *
+ * @param[in] argCert The certificate for which the CRL will be updated
+ * @param[in] updatePolicy Determine when CRL will be downloaded and updated
+ * @return True when CRL for given certificate was updated successfully,
+ * false otherwise.
+ */
+ bool updateList(const CertificatePtr &argCert,
+ const CRL::UpdatePolicy updatePolicy);
+
+ /**
+ * @brief Updates CRL related with given certificates.
+ *
+ * @details This function updates CRL lists related with given certificates.
+ * If CRL related with given certificate is not stored in database
+ * then this function will download CRL and store it in database.
+ *
+ * @param[in] collection The certificate collection for which the CRL will
+ * be updated
+ * @param[in] updatePolicy Determine when CRL will be downloaded and updated
+ * @return True when CRL for given certificate was updated successfully,
+ * false otherwise.
+ */
+ bool updateList(const CertificateCollection &collection,
+ const CRL::UpdatePolicy updatePolisy);
+
+ /**
+ * @brief Add certificates to trusted certificates store.
+ *
+ * @param[in] collection The certificate collection which will be
+ * added to known certificate store.
+ */
+ void addToStore(const CertificateCollection &collection);
+
+ /**
+ * @brief Add one certificate to trusted certificates store.
+ *
+ * @param[in] collection The certificate collection which will be
+ * added to known certificate store.
+ */
+ void addToStore(const CertificatePtr &argCert);
+};
+
+} // ValidationCore
+
+#endif // _VALIDATION_CORE_ENGINE_CRLIMPL_H_
--- /dev/null
+/*
+ * 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 CachedCRL.cpp
+ * @author Tomasz Swierczek (t.swierczek@samsung.com)
+ * @version 0.2
+ * @brief Cached CRL class implementation
+ */
+#include <vcore/CachedCRL.h>
+
+#include <dpl/foreach.h>
+#include <dpl/log/log.h>
+#include <dpl/foreach.h>
+
+#include <vcore/CRLImpl.h>
+#include <vcore/CertificateCacheDAO.h>
+#include <vcore/CRLCacheDAO.h>
+
+namespace {
+
+const time_t CRL_minTimeValid = 3600; // one hour in seconds
+
+const time_t CRL_maxTimeValid = 3600 * 24 * 7; // one week in seconds
+
+const time_t CRL_refreshBefore = 3600; // one hour in seconds
+
+time_t getNextUpdateTime(time_t now, time_t response_validity)
+{
+ time_t min = now + CRL_minTimeValid;
+ time_t max = now + CRL_maxTimeValid;
+ if (response_validity < min) {
+ return min;
+ }
+ if (response_validity > max) {
+ return max;
+ }
+ return response_validity;
+}
+
+} // namespace anonymous
+
+namespace ValidationCore {
+
+time_t CachedCRL::getCRLMinTimeValid() {
+ return CRL_minTimeValid;
+}
+
+time_t CachedCRL::getCRLMaxTimeValid() {
+ return CRL_maxTimeValid;
+}
+
+time_t CachedCRL::getCRLRefreshBefore() {
+ return CRL_refreshBefore;
+}
+
+CachedCRL::CachedCRL(){}
+CachedCRL::~CachedCRL(){}
+
+VerificationStatus CachedCRL::check(const CertificateCollection &certs)
+{
+ CRLImpl crl(new CRLCacheDAO);
+ bool allValid = true;
+ // we dont check CRL validity since
+ // we may use crl for longer time
+ // in smart cache than in regular CRL class (time clamping)
+ crl.addToStore(certs);
+ FOREACH(cert, certs){
+ CRL::StringList crlUris = crl.getCrlUris(*cert);
+ FOREACH(uri, crlUris) {
+ allValid = allValid && updateCRLForUri(*uri,false);
+ }
+ }
+ if (!allValid) {
+ // problems with CRL validity
+ LogDebug("Some CRLs not valid");
+ }
+ CRL::RevocationStatus stat;
+ Try {
+ stat = crl.checkCertificateChain(certs);
+ } Catch(CRLException::InvalidParameter) {
+ // List does not form a chain
+ return VERIFICATION_STATUS_ERROR;
+ }
+ if (stat.isRevoked) {
+ LogDebug("Status REVOKED");
+ return VERIFICATION_STATUS_REVOKED;
+ }
+ LogDebug("Status GOOD");
+ return VERIFICATION_STATUS_GOOD;
+}
+
+VerificationStatus CachedCRL::checkEndEntity(CertificateCollection &certs)
+{
+ if (certs.empty()) {
+ LogError("Collection empty. This should never happen.");
+ LogDebug("Status ERROR");
+ return VERIFICATION_STATUS_ERROR;
+ }
+ if (!certs.sort()) {
+ LogError("Could not find End Entity certificate. "
+ "Collection does not form chain.");
+ LogDebug("Status ERROR");
+ return VERIFICATION_STATUS_ERROR;
+ }
+ CRLImpl crl(new CRLCacheDAO);
+ bool allValid = true;
+ // we dont check CRL validity since
+ // we may use crl for longer time
+ // in smart cache than in regular CRL class (time clamping)
+ crl.addToStore(certs);
+ CertificateList::const_iterator icert = certs.begin();
+ if (icert != certs.end()) {
+ CRL::StringList crlUris = crl.getCrlUris(*icert);
+ FOREACH(uri, crlUris) {
+ allValid = allValid && updateCRLForUri(*uri,false);
+ }
+ }
+ if (!allValid) {
+ // problems with CRL validity
+ LogDebug("Some CRLs not valid");
+ }
+ CertificateList::const_iterator iter = certs.begin();
+ CRL::RevocationStatus stat = crl.checkCertificate(*iter);
+ if (stat.isRevoked) {
+ LogDebug("Status REVOKED");
+ return VERIFICATION_STATUS_REVOKED;
+ }
+ LogDebug("Status GOOD");
+ return VERIFICATION_STATUS_GOOD;
+}
+
+void CachedCRL::updateCache()
+{
+ CRLCachedDataList list;
+ CertificateCacheDAO::getCRLResponseList(&list);
+ FOREACH(db_crl, list) {
+ updateCRLForUri(db_crl->distribution_point, true);
+ }
+}
+
+bool CachedCRL::updateCRLForUri(const std::string &uri, bool useExpiredShift)
+{
+ using namespace ValidationCore;
+ CRLCachedData cachedCRL;
+ cachedCRL.distribution_point = uri;
+ time_t now;
+ time(&now);
+ if (useExpiredShift) {
+ now += CRL_refreshBefore;
+ }
+ if (CertificateCacheDAO::getCRLResponse(&cachedCRL)) {
+ if (now < cachedCRL.next_update_time) {
+ LogDebug("Cached CRL still valid for: " << uri);
+ return true;
+ }
+ }
+ // need to download new CRL
+ CRLImpl crl(new CRLCacheDAO);
+ CRLImpl::CRLDataPtr list = crl.downloadCRL(uri);
+ if (!list) {
+ LogWarning("Could not retreive CRL from " << uri);
+ return false;
+ }
+ crl.updateCRL(list);
+ CertificateCacheDAO::getCRLResponse(&cachedCRL); // save it the way CRL does
+ cachedCRL.next_update_time =
+ getNextUpdateTime(now,cachedCRL.next_update_time);
+ CertificateCacheDAO::setCRLResponse(cachedCRL.distribution_point,
+ cachedCRL.crl_body,
+ cachedCRL.next_update_time);
+ return true;
+}
+
+} // namespace ValidationCore
--- /dev/null
+/*
+ * 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 CachedCRL.h
+ * @author Tomasz Swierczek (t.swierczek@samsung.com)
+ * @version 0.2
+ * @brief Header file for smart cached CRL class
+ */
+
+#ifndef _VALIDATION_CORE_CACHED_CRL_H_
+#define _VALIDATION_CORE_CACHED_CRL_H_
+
+#include <ctime>
+#include <string>
+
+#include <vcore/Certificate.h>
+#include <vcore/CertificateCollection.h>
+#include <vcore/VerificationStatus.h>
+#include <vcore/IAbstractResponseCache.h>
+
+namespace ValidationCore {
+
+class CachedCRL : public IAbstractResponseCache {
+public:
+ // cache can't be refreshed more frequently than CRL_minTimeValid
+ static time_t getCRLMinTimeValid();
+
+ // to be even more secure, cache will be refreshed for certificate at least
+ // after CRL_maxTimeValid from last response
+ static time_t getCRLMaxTimeValid();
+
+ // upon cache refresh, responses that will be invalid in CRL_refreshBefore
+ // seconds will be refreshed
+ static time_t getCRLRefreshBefore();
+
+ VerificationStatus check(const CertificateCollection &certs);
+ VerificationStatus checkEndEntity(CertificateCollection &certs);
+ void updateCache();
+
+ CachedCRL();
+
+ virtual ~CachedCRL();
+
+private:
+
+ // updates CRL cache for distributor URI
+ // useExpiredShift ==true should be used in cron/global cache update
+ // since it updates all CRLs that will be out of date in next
+ // CRL_refreshBefore seconds
+ bool updateCRLForUri(const std::string & uri, bool useExpiredShift);
+};
+
+} // namespace ValidationCore
+
+#endif /* _VALIDATION_CORE_CACHED_CRL_ */
--- /dev/null
+/*
+ * 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 CachedOCSP.cpp
+ * @author Tomasz Swierczek (t.swierczek@samsung.com)
+ * @version 0.1
+ * @brief Cached OCSP class implementation
+ */
+
+#include <string>
+#include <time.h>
+
+#include <dpl/foreach.h>
+#include <dpl/log/log.h>
+#include <dpl/foreach.h>
+
+#include <vcore/OCSP.h>
+#include <vcore/OCSPImpl.h>
+#include <vcore/CachedOCSP.h>
+#include <vcore/Certificate.h>
+#include <vcore/CertificateCacheDAO.h>
+
+namespace {
+
+// one hour in seconds
+const time_t OCSP_minTimeValid = 3600; // one hour in seconds
+
+// one week in seconds
+const time_t OCSP_maxTimeValid = 3600 * 24 * 7;
+
+// one hour in seconds
+const time_t OCSP_refreshBefore = 3600;
+
+} // anonymous namespace
+
+namespace ValidationCore {
+
+time_t CachedOCSP::getOCSPMinTimeValid() {
+ return OCSP_minTimeValid;
+}
+
+time_t CachedOCSP::getOCSPMaxTimeValid() {
+ return OCSP_maxTimeValid;
+}
+
+time_t CachedOCSP::getOCSPRefreshBefore() {
+ return OCSP_refreshBefore;
+}
+
+CachedOCSP::CachedOCSP(){}
+
+CachedOCSP::~CachedOCSP(){}
+
+VerificationStatus CachedOCSP::check(const CertificateCollection &certs)
+{
+ OCSPCachedStatus db_status;
+ time_t now;
+ time(&now);
+
+ db_status.cert_chain = certs.toBase64String();
+ db_status.end_entity_check = false;
+
+ if (CertificateCacheDAO::getOCSPStatus(&db_status)) {
+ LogDebug("Found cache entry for OCSP");
+ if (now < db_status.next_update_time) {
+ LogDebug("Cache response valid");
+ return db_status.ocsp_status;
+ }
+ }
+
+ // here we need to get OCSP result and add/update cache
+ OCSP ocsp;
+ CertificateList list = certs.getChain();
+ ocsp.setTrustedStore(list);
+
+ VerificationStatusSet statusSet = ocsp.validateCertificateList(list);
+ db_status.ocsp_status = statusSet.convertToStatus();
+ db_status.next_update_time = ocsp.getResponseValidity();
+ CertificateCacheDAO::setOCSPStatus(db_status.cert_chain,
+ db_status.ocsp_status,
+ db_status.end_entity_check,
+ getNextUpdateTime(
+ now,
+ db_status.next_update_time));
+ return db_status.ocsp_status;
+}
+
+VerificationStatus CachedOCSP::checkEndEntity(CertificateCollection &certs)
+{
+ OCSPCachedStatus db_status;
+ time_t now;
+ time(&now);
+
+ db_status.cert_chain = certs.toBase64String();
+ db_status.end_entity_check = true;
+
+ if (CertificateCacheDAO::getOCSPStatus(&db_status)) {
+ LogDebug("Found cache entry for OCSP");
+ if (now < db_status.next_update_time) {
+ LogDebug("Cache response valid");
+ return db_status.ocsp_status;
+ }
+ }
+
+ // here we need to send request via OCSP and add/update cache
+ CertificateList clst;
+ getCertsForEndEntity(certs, &clst);
+
+ OCSP ocsp;
+ ocsp.setTrustedStore(certs.getCertificateList());
+
+ const char *defResponderURI = getenv(OCSPImpl::DEFAULT_RESPONDER_URI_ENV);
+
+ if (defResponderURI) {
+ ocsp.setUseDefaultResponder(true);
+ ocsp.setDefaultResponder(defResponderURI);
+ }
+
+ VerificationStatusSet statusSet = ocsp.validateCertificateList(clst);
+ db_status.ocsp_status = statusSet.convertToStatus();
+ db_status.next_update_time = ocsp.getResponseValidity();
+
+ CertificateCacheDAO::setOCSPStatus(db_status.cert_chain,
+ db_status.ocsp_status,
+ db_status.end_entity_check,
+ getNextUpdateTime(
+ now,
+ db_status.next_update_time));
+
+ return db_status.ocsp_status;
+}
+
+void CachedOCSP::updateCache()
+{
+ time_t now;
+ time(&now);
+ now += OCSP_refreshBefore;
+ OCSPCachedStatusList list;
+ CertificateCacheDAO::getOCSPStatusList(&list);
+ FOREACH(db_status, list) {
+ if (now >= db_status->next_update_time) {
+ // this response needs to be refreshed
+ CertificateCollection col;
+ col.load(db_status->cert_chain);
+ if (!col.sort()) {
+ LogError("Certificate collection does not create chain.");
+ continue;
+ }
+
+ OCSP ocsp;
+ CertificateList chain = col.getChain();
+ ocsp.setTrustedStore(chain);
+
+ VerificationStatusSet statusSet;
+
+ if (db_status->end_entity_check) {
+ CertificateList clst;
+ getCertsForEndEntity(col, &clst);
+ statusSet = ocsp.validateCertificateList(clst);
+ } else {
+ statusSet = ocsp.validateCertificateList(chain);
+ }
+
+ db_status->ocsp_status = statusSet.convertToStatus();
+ db_status->next_update_time = ocsp.getResponseValidity();
+
+ CertificateCacheDAO::setOCSPStatus(db_status->cert_chain,
+ db_status->ocsp_status,
+ db_status->end_entity_check,
+ db_status->next_update_time);
+ }
+ }
+}
+
+void CachedOCSP::getCertsForEndEntity(
+ const CertificateCollection &certs, CertificateList* clst)
+{
+ if (NULL == clst) {
+ LogError("NULL pointer");
+ return;
+ }
+
+ if (certs.isChain() && certs.size() >= 2) {
+ CertificateList::const_iterator icert = certs.begin();
+ clst->push_back(*icert);
+ ++icert;
+ clst->push_back(*icert);
+ }
+}
+
+time_t CachedOCSP::getNextUpdateTime(time_t now, time_t response_validity)
+{
+ long min = now + OCSP_minTimeValid;
+ long max = now + OCSP_maxTimeValid;
+ if (response_validity < min) {
+ return min;
+ }
+ if (response_validity > max) {
+ return max;
+ }
+ return response_validity;
+}
+
+} // namespace ValidationCore
--- /dev/null
+/*
+ * 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 CachedOCSP.h
+ * @author Tomasz Swierczek (t.swierczek@samsung.com)
+ * @version 0.1
+ * @brief Header file for smart cached OCSP class
+ */
+
+#ifndef _SRC_VALIDATION_CORE_CACHED_OCSP_
+#define _SRC_VALIDATION_CORE_CACHED_OCSP_
+
+#include <vcore/OCSP.h>
+#include <vcore/IAbstractResponseCache.h>
+
+namespace ValidationCore {
+
+class CachedOCSP : public IAbstractResponseCache {
+ public:
+ // cache can't be refreshed more frequently than OCSP_minTimeValid
+ static time_t getOCSPMinTimeValid();
+ // to be even more secure, cache will be refreshed for certificate at least
+ // after OCSP_minTimeValid from last response
+ static time_t getOCSPMaxTimeValid();
+
+ // upon cache refresh, responses that will be invalid in OCSP_refreshBefore
+ // seconds will be refreshed
+ static time_t getOCSPRefreshBefore();
+
+ VerificationStatus check(const CertificateCollection &certs);
+ VerificationStatus checkEndEntity(CertificateCollection &certs);
+ void updateCache();
+
+ CachedOCSP();
+
+ virtual ~CachedOCSP();
+
+ private:
+
+ void getCertsForEndEntity(const CertificateCollection &certs,
+ CertificateList* clst);
+ time_t getNextUpdateTime(time_t now, time_t response_validity);
+};
+
+} // namespace ValidationCore
+
+#endif /* _SRC_VALIDATION_CORE_CACHED_OCSP_ */
--- /dev/null
+/*
+ * 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.
+ */
+/*
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @file CertStoreType.cpp
+ * @version 1.0
+ * @brief Identification of certificate domain. Certificate domains
+ * were defined in WAC 1.0 documentation. This is a part
+ * should be implemented in wrt-installer.
+ */
+#include <vcore/CertStoreType.h>
+
+namespace ValidationCore {
+namespace CertStoreId {
+
+Set::Set()
+ : m_certificateStorage(0)
+{}
+
+void Set::add(Type second) {
+ m_certificateStorage |= second;
+}
+
+bool Set::contains(Type second) const {
+ return static_cast<bool>(m_certificateStorage & second);
+}
+
+bool Set::isEmpty() const {
+ return m_certificateStorage == 0;
+}
+
+} // namespace CertStoreId
+} // namespace ValidationCore
--- /dev/null
+/*
+ * 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.
+ */
+/*
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @file CertStoreType.h
+ * @version 1.0
+ * @brief Identification of certificate domain. Certificate domains
+ * were defined in WAC 1.0 documentation. This is a part
+ * should be implemented in wrt-installer.
+ */
+#ifndef _VALIDATION_CORE_CERTSTORETYPE_H_
+#define _VALIDATION_CORE_CERTSTORETYPE_H_
+
+namespace ValidationCore {
+namespace CertStoreId {
+typedef unsigned int Type;
+
+// RootCA certificates for developer mode.
+const Type DEVELOPER = 1;
+// RootCA certificates for author signatures.
+const Type WAC_PUBLISHER = 1 << 1;
+// RootCA certificates for wac-signed widgets.
+const Type WAC_ROOT = 1 << 2;
+// RootCA certificates for wac-members ie. operators, manufacturers.
+const Type WAC_MEMBER = 1 << 3;
+// RootCA certificates for tizen-member ie. samsung and operators
+const Type TIZEN_MEMBER = 1 << 4;
+// RootCA certificates used by orange
+const Type ORANGE_LEGACY = 1 << 5;
+
+class Set
+{
+ public:
+ Set();
+
+ void add(Type second);
+
+ bool contains(Type second) const;
+
+ bool isEmpty() const;
+
+ private:
+ Type m_certificateStorage;
+};
+
+} // namespace CertStoreId
+} // namespace ValidationCore
+
+#endif // _VALIDATION_CORE_CERTSTORETYPE_H_
--- /dev/null
+/*
+ * 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 Certificate.cpp
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief
+ */
+#include <vcore/Certificate.h>
+
+#include <memory>
+#include <sstream>
+#include <iomanip>
+
+#include <openssl/x509v3.h>
+#include <openssl/bn.h>
+
+#include <dpl/assert.h>
+#include <dpl/log/log.h>
+
+#include <vcore/Base64.h>
+#include <vcore/TimeConversion.h>
+
+namespace ValidationCore {
+
+Certificate::Certificate(X509 *cert)
+{
+ Assert(cert);
+ m_x509 = X509_dup(cert);
+ if (!m_x509) {
+ LogWarning("Internal Openssl error in d2i_X509 function.");
+ ThrowMsg(Exception::OpensslInternalError,
+ "Internal Openssl error in d2i_X509 function.");
+ }
+}
+
+Certificate::Certificate(cert_svc_mem_buff &buffer)
+{
+ Assert(buffer.data);
+ const unsigned char *ptr = buffer.data;
+ m_x509 = d2i_X509(NULL, &ptr, buffer.size);
+ if (!m_x509) {
+ LogWarning("Internal Openssl error in d2i_X509 function.");
+ ThrowMsg(Exception::OpensslInternalError,
+ "Internal Openssl error in d2i_X509 function.");
+ }
+}
+
+Certificate::Certificate(const std::string &der,
+ Certificate::FormType form)
+{
+ Assert(der.size());
+
+ int size;
+ const unsigned char *ptr;
+ std::string tmp;
+
+ if (FORM_BASE64 == form) {
+ Base64Decoder base64;
+ base64.reset();
+ base64.append(der);
+ base64.finalize();
+ tmp = base64.get();
+ ptr = reinterpret_cast<const unsigned char*>(tmp.c_str());
+ size = static_cast<int>(tmp.size());
+ } else {
+ ptr = reinterpret_cast<const unsigned char*>(der.c_str());
+ size = static_cast<int>(der.size());
+ }
+
+ m_x509 = d2i_X509(NULL, &ptr, size);
+ if (!m_x509) {
+ LogError("Internal Openssl error in d2i_X509 function.");
+ ThrowMsg(Exception::OpensslInternalError,
+ "Internal Openssl error in d2i_X509 function.");
+ }
+}
+
+Certificate::~Certificate()
+{
+ X509_free(m_x509);
+}
+
+X509* Certificate::getX509(void) const
+{
+ return m_x509;
+}
+
+std::string Certificate::getDER(void) const
+{
+ unsigned char *rawDer = NULL;
+ int size = i2d_X509(m_x509, &rawDer);
+ if (!rawDer || size <= 0) {
+ LogError("i2d_X509 failed");
+ ThrowMsg(Exception::OpensslInternalError,
+ "i2d_X509 failed");
+ }
+
+ std::string output(reinterpret_cast<char*>(rawDer), size);
+ OPENSSL_free(rawDer);
+ return output;
+}
+
+std::string Certificate::getBase64(void) const
+{
+ Base64Encoder base64;
+ base64.reset();
+ base64.append(getDER());
+ base64.finalize();
+ return base64.get();
+}
+
+bool Certificate::isSignedBy(const CertificatePtr &parent) const
+{
+ if (!parent) {
+ LogDebug("Invalid certificate parameter.");
+ return false;
+ }
+ return 0 == X509_NAME_cmp(X509_get_subject_name(parent->m_x509),
+ X509_get_issuer_name(m_x509));
+}
+
+Certificate::Fingerprint Certificate::getFingerprint(
+ Certificate::FingerprintType type) const
+{
+ size_t fingerprintlength = EVP_MAX_MD_SIZE;
+ unsigned char fingerprint[EVP_MAX_MD_SIZE];
+ Fingerprint raw;
+
+ if (type == FINGERPRINT_MD5) {
+ if (!X509_digest(m_x509, EVP_md5(), fingerprint, &fingerprintlength)) {
+ LogError("MD5 digest counting failed!");
+ ThrowMsg(Exception::OpensslInternalError,
+ "MD5 digest counting failed!");
+ }
+ }
+
+ if (type == FINGERPRINT_SHA1) {
+ if (!X509_digest(m_x509, EVP_sha1(), fingerprint,
+ &fingerprintlength))
+ {
+ LogError("SHA1 digest counting failed");
+ ThrowMsg(Exception::OpensslInternalError,
+ "SHA1 digest counting failed!");
+ }
+ }
+
+ raw.resize(fingerprintlength); // improve performance
+ std::copy(fingerprint, fingerprint + fingerprintlength, raw.begin());
+
+ return raw;
+}
+
+X509_NAME *Certificate::getX509Name(FieldType type) const
+{
+ X509_NAME *name = NULL;
+
+ switch (type) {
+ case FIELD_ISSUER:
+ name = X509_get_issuer_name(m_x509);
+ break;
+ case FIELD_SUBJECT:
+ name = X509_get_subject_name(m_x509);
+ break;
+ default:
+ Assert("Invalid field type.");
+ }
+
+ if (!name) {
+ LogError("Error during x509 name extraction.");
+ ThrowMsg(Exception::OpensslInternalError,
+ "Error during x509 name extraction.");
+ }
+
+ return name;
+}
+
+DPL::String Certificate::getOneLine(FieldType type) const
+{
+ X509_NAME *name = getX509Name(type);
+ static const int MAXB = 1024;
+ char buffer[MAXB];
+ X509_NAME_oneline(name, buffer, MAXB);
+ return DPL::FromUTF8String(buffer);
+}
+
+DPL::OptionalString Certificate::getField(FieldType type,
+ int fieldNid) const
+{
+ X509_NAME *subjectName = getX509Name(type);
+ X509_NAME_ENTRY *subjectEntry = NULL;
+ DPL::Optional < DPL::String > output;
+ int entryCount = X509_NAME_entry_count(subjectName);
+
+ for (int i = 0; i < entryCount; ++i) {
+ subjectEntry = X509_NAME_get_entry(subjectName,
+ i);
+
+ if (!subjectEntry) {
+ continue;
+ }
+
+ int nid = OBJ_obj2nid(
+ static_cast<ASN1_OBJECT*>(
+ X509_NAME_ENTRY_get_object(subjectEntry)));
+
+ if (nid != fieldNid) {
+ continue;
+ }
+
+ ASN1_STRING* pASN1Str = subjectEntry->value;
+
+ unsigned char* pData = NULL;
+ int nLength = ASN1_STRING_to_UTF8(&pData,
+ pASN1Str);
+
+ if (nLength < 0) {
+ LogError("Reading field error.");
+ ThrowMsg(Exception::OpensslInternalError,
+ "Reading field error.");
+ }
+
+ std::string strEntry(reinterpret_cast<char*>(pData),
+ nLength);
+ output = DPL::FromUTF8String(strEntry);
+ OPENSSL_free(pData);
+ }
+ return output;
+}
+
+DPL::OptionalString Certificate::getCommonName(FieldType type) const
+{
+ return getField(type, NID_commonName);
+}
+
+DPL::OptionalString Certificate::getCountryName(FieldType type) const
+{
+ return getField(type, NID_countryName);
+}
+
+DPL::OptionalString Certificate::getStateOrProvinceName(FieldType type) const
+{
+ return getField(type, NID_stateOrProvinceName);
+}
+
+DPL::OptionalString Certificate::getLocalityName(FieldType type) const
+{
+ return getField(type, NID_localityName);
+}
+
+DPL::OptionalString Certificate::getOrganizationName(FieldType type) const
+{
+ return getField(type, NID_organizationName);
+}
+
+DPL::OptionalString Certificate::getOrganizationalUnitName(FieldType type) const
+{
+ return getField(type, NID_organizationalUnitName);
+}
+
+DPL::OptionalString Certificate::getEmailAddres(FieldType type) const
+{
+ return getField(type, NID_pkcs9_emailAddress);
+}
+
+DPL::OptionalString Certificate::getOCSPURL() const
+{
+ // TODO verify this code
+ DPL::OptionalString retValue;
+ AUTHORITY_INFO_ACCESS *aia = static_cast<AUTHORITY_INFO_ACCESS*>(
+ X509_get_ext_d2i(m_x509,
+ NID_info_access,
+ NULL,
+ NULL));
+
+ // no AIA extension in the cert
+ if (NULL == aia) {
+ return retValue;
+ }
+
+ int count = sk_ACCESS_DESCRIPTION_num(aia);
+
+ for (int i = 0; i < count; ++i) {
+ ACCESS_DESCRIPTION* ad = sk_ACCESS_DESCRIPTION_value(aia, i);
+
+ if (OBJ_obj2nid(ad->method) == NID_ad_OCSP &&
+ ad->location->type == GEN_URI)
+ {
+ void* data = ASN1_STRING_data(ad->location->d.ia5);
+ retValue = DPL::OptionalString(DPL::FromUTF8String(
+ static_cast<char*>(data)));
+
+ break;
+ }
+ }
+ sk_ACCESS_DESCRIPTION_free(aia);
+ return retValue;
+}
+
+Certificate::AltNameSet Certificate::getAlternativeNameDNS() const
+{
+ AltNameSet set;
+
+ GENERAL_NAME *namePart = NULL;
+
+ STACK_OF(GENERAL_NAME)* san =
+ static_cast<STACK_OF(GENERAL_NAME)*>(
+ X509_get_ext_d2i(m_x509,NID_subject_alt_name,NULL,NULL));
+
+ while (sk_GENERAL_NAME_num(san) > 0) {
+ namePart = sk_GENERAL_NAME_pop(san);
+ if (GEN_DNS == namePart->type) {
+ std::string temp =
+ reinterpret_cast<char*>(ASN1_STRING_data(namePart->d.dNSName));
+ DPL::String altDNSName = DPL::FromASCIIString(temp);
+ set.insert(altDNSName);
+ LogDebug("FOUND GEN_DNS: " << temp);
+ } else {
+ LogDebug("FOUND GEN TYPE ID: " << namePart->type);
+ }
+ }
+ return set;
+}
+
+time_t Certificate::getNotAfter() const
+{
+ ASN1_TIME *time = X509_get_notAfter(m_x509);
+ if (!time) {
+ LogError("Reading Not After error.");
+ ThrowMsg(Exception::OpensslInternalError, "Reading Not After error.");
+ }
+ time_t output;
+ if (asn1TimeToTimeT(time, &output)) {
+ LogError("Converting ASN1_time to time_t error.");
+ ThrowMsg(Exception::OpensslInternalError,
+ "Converting ASN1_time to time_t error.");
+ }
+ return output;
+}
+
+time_t Certificate::getNotBefore() const
+{
+ ASN1_TIME *time = X509_get_notBefore(m_x509);
+ if (!time) {
+ LogError("Reading Not Before error.");
+ ThrowMsg(Exception::OpensslInternalError, "Reading Not Before error.");
+ }
+ time_t output;
+ if (asn1TimeToTimeT(time, &output)) {
+ LogError("Converting ASN1_time to time_t error.");
+ ThrowMsg(Exception::OpensslInternalError,
+ "Converting ASN1_time to time_t error.");
+ }
+ return output;
+}
+
+bool Certificate::isRootCert()
+{
+ // based on that root certificate has the same subject as issuer name
+ return isSignedBy(this->SharedFromThis());
+}
+
+std::list<std::string>
+Certificate::getCrlUris() const
+{
+ std::list<std::string> result;
+
+ STACK_OF(DIST_POINT)* distPoints =
+ static_cast<STACK_OF(DIST_POINT)*>(
+ X509_get_ext_d2i(
+ getX509(),
+ NID_crl_distribution_points,
+ NULL,
+ NULL));
+ if (!distPoints) {
+ LogDebug("No distribution points in certificate.");
+ return result;
+ }
+
+ int count = sk_DIST_POINT_num(distPoints);
+ for (int i = 0; i < count; ++i) {
+ DIST_POINT* point = sk_DIST_POINT_value(distPoints, i);
+ if (!point) {
+ LogError("Failed to get distribution point.");
+ continue;
+ }
+ if (point->distpoint != NULL &&
+ point->distpoint->name.fullname != NULL)
+ {
+ int countName =
+ sk_GENERAL_NAME_num(point->distpoint->name.fullname);
+ for (int j = 0; j < countName; ++j) {
+ GENERAL_NAME* name = sk_GENERAL_NAME_value(
+ point->distpoint->name.fullname, j);
+ if (name != NULL && GEN_URI == name->type) {
+ char *crlUri =
+ reinterpret_cast<char*>(name->d.ia5->data);
+ if (!crlUri) {
+ LogError("Failed to get URI.");
+ continue;
+ }
+ result.push_back(crlUri);
+ }
+ }
+ }
+ }
+ sk_DIST_POINT_pop_free(distPoints, DIST_POINT_free);
+ return result;
+}
+
+long Certificate::getVersion() const
+{
+ return X509_get_version(m_x509);
+}
+
+DPL::String Certificate::getSerialNumberString() const
+{
+ ASN1_INTEGER *ai = X509_get_serialNumber(m_x509);
+ if (NULL == ai) {
+ LogError("Error in X509_get_serialNumber");
+ ThrowMsg(Exception::OpensslInternalError,
+ "Error in X509_get_serialNumber");
+ }
+ std::stringstream stream;
+ stream << std::hex << std::setfill('0');
+ if (ai->type == V_ASN1_NEG_INTEGER) {
+ stream << "(Negetive) ";
+ }
+ for (int i=0; i<ai->length; ++i) {
+ stream << std::setw(2) << (int)ai->data[i] << ":";
+ }
+ std::string data = stream.str();
+ if (!data.empty()) {
+ data.erase(--data.end());
+ }
+ return DPL::FromUTF8String(data);
+}
+
+DPL::String Certificate::getKeyUsageString() const
+{
+ // Extensions were defined in RFC 3280
+ const char *usage[] = {
+ "digitalSignature",
+ "nonRepudiation",
+ "keyEncipherment",
+ "dataEncipherment",
+ "keyAgreement",
+ "keyCertSign",
+ "cRLSign",
+ "encipherOnly",
+ "decipherOnly"
+ };
+ int crit = -1;
+ int idx = -1;
+ ASN1_BIT_STRING *keyUsage = (ASN1_BIT_STRING*)
+ X509_get_ext_d2i(m_x509, NID_key_usage, &crit, &idx);
+
+ std::stringstream stream;
+ for(int i=0; i<9; ++i) {
+ if (ASN1_BIT_STRING_get_bit(keyUsage, i)) {
+ stream << usage[i] << ",";
+ }
+ }
+ std::string result = stream.str();
+ if (!result.empty()) {
+ result.erase(--result.end());
+ }
+ return DPL::FromUTF8String(result);
+}
+
+DPL::String Certificate::getSignatureAlgorithmString() const
+{
+ std::unique_ptr<BIO, std::function<int(BIO*)>>
+ b(BIO_new(BIO_s_mem()),BIO_free);
+
+ if (b.get() == NULL) {
+ LogError("Error in BIO_new");
+ ThrowMsg(Exception::OpensslInternalError,
+ "Error in BIO_new");
+ }
+ if (i2a_ASN1_OBJECT(b.get(), m_x509->cert_info->signature->algorithm) < 0) {
+ LogError("Error in i2a_ASN1_OBJECT");
+ ThrowMsg(Exception::OpensslInternalError,
+ "Error in i2a_ASN1_OBJECT");
+ }
+ BUF_MEM *bptr = 0;
+ BIO_get_mem_ptr(b.get(), &bptr);
+ if (bptr == 0) {
+ LogError("Error in BIO_get_mem_ptr");
+ ThrowMsg(Exception::OpensslInternalError,
+ "Error in BIO_get_mem_ptr");
+ }
+ std::string result(bptr->data, bptr->length);
+ return DPL::FromUTF8String(result);
+}
+
+DPL::String Certificate::getPublicKeyString() const
+{
+ std::unique_ptr<BIO, std::function<int(BIO*)>>
+ b(BIO_new(BIO_s_mem()),BIO_free);
+
+ if (b.get() == NULL) {
+ LogError("Error in BIO_new");
+ ThrowMsg(Exception::OpensslInternalError,
+ "Error in BIO_new");
+ }
+ EVP_PKEY *pkey = X509_get_pubkey(m_x509);
+ if (pkey == NULL) {
+ LogError("Error in X509_get_pubkey");
+ ThrowMsg(Exception::OpensslInternalError,
+ "Error in X509_get_pubkey");
+ }
+ EVP_PKEY_print_public(b.get(), pkey, 16, NULL);
+ EVP_PKEY_free(pkey);
+
+ BUF_MEM *bptr = 0;
+ BIO_get_mem_ptr(b.get(), &bptr);
+ if (bptr == 0) {
+ LogError("Error in BIO_get_mem_ptr");
+ ThrowMsg(Exception::OpensslInternalError,
+ "Error in BIO_get_mem_ptr");
+ }
+ std::string result(bptr->data, bptr->length);
+ return DPL::FromUTF8String(result);
+}
+
+int Certificate::isCA() const {
+ return X509_check_ca(m_x509);
+}
+
+std::string Certificate::FingerprintToColonHex(
+ const Certificate::Fingerprint &fingerprint)
+{
+ std::string outString;
+ char buff[8];
+
+ for (size_t i = 0; i < fingerprint.size(); ++i) {
+ snprintf(buff,
+ sizeof(buff),
+ "%02X:",
+ static_cast<unsigned int>(fingerprint[i]));
+ outString += buff;
+ }
+
+ // remove trailing ":"
+ outString.erase(outString.end() - 1);
+ return outString;
+}
+
+} // namespace ValidationCore
--- /dev/null
+/*
+ * 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 Certificate.h
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.1
+ * @brief
+ */
+#ifndef _VALIDATION_CORE_CERTIFICATE_H_
+#define _VALIDATION_CORE_CERTIFICATE_H_
+
+#include <list>
+#include <set>
+#include <string>
+#include <vector>
+#include <ctime>
+
+#include <dpl/exception.h>
+#include <dpl/noncopyable.h>
+#include <dpl/shared_ptr.h>
+#include <dpl/enable_shared_from_this.h>
+#include <dpl/optional.h>
+#include <dpl/optional_typedefs.h>
+#include <dpl/string.h>
+
+#include <cert-service.h>
+
+extern "C" {
+struct x509_st;
+typedef struct x509_st X509;
+struct X509_name_st;
+typedef struct X509_name_st X509_NAME;
+}
+
+namespace ValidationCore {
+
+class Certificate;
+
+typedef DPL::SharedPtr<Certificate> CertificatePtr;
+typedef std::list<CertificatePtr> CertificateList;
+
+class Certificate : public DPL::EnableSharedFromThis<Certificate>
+{
+ public:
+ typedef std::vector<unsigned char> Fingerprint;
+ typedef DPL::String AltName;
+ typedef std::set<AltName> AltNameSet;
+
+ enum FingerprintType
+ {
+ FINGERPRINT_MD5,
+ FINGERPRINT_SHA1
+ };
+ enum FieldType
+ {
+ FIELD_ISSUER,
+ FIELD_SUBJECT
+ };
+
+ enum FormType
+ {
+ FORM_DER,
+ FORM_BASE64
+ };
+
+ class Exception
+ {
+ public:
+ DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
+ DECLARE_EXCEPTION_TYPE(Base, OpensslInternalError)
+ };
+
+ explicit Certificate(X509 *cert);
+
+ explicit Certificate(cert_svc_mem_buff &buffer);
+
+ explicit Certificate(const std::string &der,
+ FormType form = FORM_DER);
+
+ ~Certificate();
+
+ // It returns pointer to internal structure!
+ // Do not free this pointer!
+ X509 *getX509(void) const;
+
+ std::string getDER(void) const;
+
+ std::string getBase64(void) const;
+
+ // This const is cheating here because you have no
+ // guarantee that X509_get_subject_name will not
+ // change X509 object.
+ bool isSignedBy(const CertificatePtr &parent) const;
+
+ Fingerprint getFingerprint(FingerprintType type) const;
+
+ // getName uses deprecated functions. Usage is strongly discouraged.
+ DPL::String getOneLine(FieldType type = FIELD_SUBJECT) const;
+ DPL::OptionalString getCommonName(FieldType type = FIELD_SUBJECT) const;
+ DPL::OptionalString getCountryName(FieldType type = FIELD_SUBJECT) const;
+ DPL::OptionalString getStateOrProvinceName(
+ FieldType type = FIELD_SUBJECT) const;
+ DPL::OptionalString getLocalityName(FieldType type = FIELD_SUBJECT) const;
+ DPL::OptionalString getOrganizationName(
+ FieldType type = FIELD_SUBJECT) const;
+ DPL::OptionalString getOrganizationalUnitName(
+ FieldType type = FIELD_SUBJECT) const;
+ DPL::OptionalString getEmailAddres(FieldType type = FIELD_SUBJECT) const;
+ DPL::OptionalString getOCSPURL() const;
+
+ // Openssl supports 9 types of alternative name filed.
+ // 4 of them are "string similar" types so it is possible
+ // to create more generic function.
+ AltNameSet getAlternativeNameDNS() const;
+
+ time_t getNotAfter() const;
+
+ time_t getNotBefore() const;
+
+ /**
+ * @brief This is convenient function.
+ *
+ * @details It can't be const function (however it doesn't change internal
+ * object). For details see #isSignedBy() function description.
+ */
+ bool isRootCert();
+
+ /**
+ * @brief Gets list of CRL distribution's points URIs
+ */
+ std::list<std::string> getCrlUris() const;
+
+ long getVersion() const;
+
+ DPL::String getSerialNumberString() const;
+
+ DPL::String getKeyUsageString() const;
+
+ DPL::String getSignatureAlgorithmString() const;
+
+ DPL::String getPublicKeyString() const;
+
+ /*
+ * 0 - not CA
+ * 1 - CA
+ * 2 - deprecated and not used
+ * 3 - older version of CA
+ * 4 - older version of CA
+ * 5 - netscape CA
+ */
+ int isCA() const;
+
+ static std::string FingerprintToColonHex(
+ const Fingerprint &fingerprint);
+
+ protected:
+ X509_NAME *getX509Name(FieldType type) const;
+
+ DPL::OptionalString getField(FieldType type,
+ int fieldNid) const;
+
+ X509 *m_x509;
+};
+} // namespace ValidationCore
+
+#endif // _VALIDATION_CORE_CERTIFICATE_H_
--- /dev/null
+/*
+ * 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 CertificateCacheDAO.cpp
+ * @author Tomasz Swierczek (t.swierczek@samsung.com)
+ * @version 0.1
+ * @brief CertificateCacheDAO implementation
+ */
+
+#include <vcore/CertificateCacheDAO.h>
+#include <vcore/VCorePrivate.h>
+
+#include <dpl/foreach.h>
+#include <dpl/log/log.h>
+#include <dpl/db/orm.h>
+#include <orm_generator_vcore.h>
+#include <vcore/Database.h>
+
+using namespace DPL::DB::ORM;
+using namespace DPL::DB::ORM::vcore;
+
+namespace ValidationCore {
+
+void CertificateCacheDAO::setOCSPStatus(const std::string& cert_chain,
+ VerificationStatus ocsp_status,
+ bool end_entity_check,
+ time_t next_update_time)
+{
+ Try {
+ ScopedTransaction transaction(&ThreadInterface());
+ OCSPCachedStatus status;
+ status.cert_chain = cert_chain;
+ status.end_entity_check = end_entity_check;
+ if (getOCSPStatus(&status)) {
+ // only need to update data in DB
+ Equals<OCSPResponseStorage::cert_chain> e1(
+ DPL::FromUTF8String(cert_chain));
+ Equals<OCSPResponseStorage::end_entity_check> e2(
+ end_entity_check ? 1 : 0);
+
+ OCSPResponseStorage::Row row;
+
+ row.Set_ocsp_status(ocsp_status);
+ row.Set_next_update_time(next_update_time);
+
+ VCORE_DB_UPDATE(update, OCSPResponseStorage, &ThreadInterface())
+ update->Where(And(e1,e2));
+ update->Values(row);
+ update->Execute();
+ } else {
+ // need to insert data
+ OCSPResponseStorage::Row row;
+
+ row.Set_cert_chain(DPL::FromUTF8String(cert_chain));
+ row.Set_ocsp_status(ocsp_status);
+ row.Set_next_update_time(next_update_time);
+ row.Set_end_entity_check(end_entity_check ? 1 : 0);
+
+ VCORE_DB_INSERT(insert, OCSPResponseStorage, &ThreadInterface())
+ insert->Values(row);
+ insert->Execute();
+ }
+ transaction.Commit();
+ } Catch(DPL::DB::SqlConnection::Exception::Base) {
+ ReThrowMsg(Exception::DatabaseError, "Failed to setOCSPStatus");
+ }
+}
+
+bool CertificateCacheDAO::getOCSPStatus(OCSPCachedStatus* cached_status)
+{
+ if (NULL == cached_status) {
+ LogError("NULL pointer");
+ return false;
+ }
+ Try {
+ Equals<OCSPResponseStorage::cert_chain> e1(
+ DPL::FromUTF8String(cached_status->cert_chain));
+ Equals<OCSPResponseStorage::end_entity_check> e2(
+ cached_status->end_entity_check ? 1 : 0);
+
+ VCORE_DB_SELECT(select, OCSPResponseStorage, &ThreadInterface())
+
+ select->Where(And(e1,e2));
+ std::list<OCSPResponseStorage::Row> rows = select->GetRowList();
+ if (1 == rows.size()) {
+ OCSPResponseStorage::Row row = rows.front();
+ cached_status->ocsp_status = intToVerificationStatus(
+ *(row.Get_ocsp_status()));
+ cached_status->next_update_time = *(row.Get_next_update_time());
+ return true;
+ }
+
+ LogDebug("Cached OCSP status not found");
+ return false;
+ }
+ Catch(DPL::DB::SqlConnection::Exception::Base) {
+ ReThrowMsg(Exception::DatabaseError, "Failed to getOCSPStatus");
+ }
+}
+
+void CertificateCacheDAO::getOCSPStatusList(
+ OCSPCachedStatusList* cached_status_list)
+{
+ if (NULL == cached_status_list) {
+ LogError("NULL pointer");
+ return;
+ }
+ Try {
+ VCORE_DB_SELECT(select, OCSPResponseStorage, &ThreadInterface())
+ typedef std::list<OCSPResponseStorage::Row> RowList;
+ RowList list = select->GetRowList();
+
+ FOREACH(i, list) {
+ OCSPCachedStatus status;
+ status.cert_chain = DPL::ToUTF8String(i->Get_cert_chain());
+ status.ocsp_status = intToVerificationStatus(
+ *(i->Get_ocsp_status()));
+ status.end_entity_check =
+ *(i->Get_end_entity_check()) == 1 ? true : false;
+ status.next_update_time = *(i->Get_next_update_time());
+ cached_status_list->push_back(status);
+ }
+
+ }
+ Catch(DPL::DB::SqlConnection::Exception::Base) {
+ ReThrowMsg(Exception::DatabaseError, "Failed to getOCSPStatusList");
+ }
+}
+
+
+void CertificateCacheDAO::setCRLResponse(const std::string& distribution_point,
+ const std::string& crl_body,
+ time_t next_update_time)
+{
+ Try {
+ ScopedTransaction transaction(&ThreadInterface());
+ CRLCachedData data;
+ data.distribution_point = distribution_point;
+ if (getCRLResponse(&data)) {
+ // only need to update data in DB
+ VCORE_DB_UPDATE(update, CRLResponseStorage, &ThreadInterface())
+ Equals<CRLResponseStorage::distribution_point> e1(
+ DPL::FromUTF8String(distribution_point));
+ CRLResponseStorage::Row row;
+
+ update->Where(e1);
+ row.Set_crl_body(DPL::FromUTF8String(crl_body));
+ row.Set_next_update_time(next_update_time);
+ update->Values(row);
+ update->Execute();
+ } else {
+ // need to insert data
+ VCORE_DB_INSERT(insert, CRLResponseStorage, &ThreadInterface())
+ CRLResponseStorage::Row row;
+
+ row.Set_distribution_point(DPL::FromUTF8String(distribution_point));
+ row.Set_crl_body(DPL::FromUTF8String(crl_body));
+ row.Set_next_update_time(next_update_time);
+ insert->Values(row);
+ insert->Execute();
+ }
+ transaction.Commit();
+ } Catch(DPL::DB::SqlConnection::Exception::Base) {
+ ReThrowMsg(Exception::DatabaseError, "Failed to setOCSPStatus");
+ }
+}
+
+bool CertificateCacheDAO::getCRLResponse(CRLCachedData* cached_data)
+{
+ if (NULL == cached_data) {
+ LogError("NULL pointer");
+ return false;
+ }
+ Try {
+ VCORE_DB_SELECT(select, CRLResponseStorage, &ThreadInterface())
+ Equals<CRLResponseStorage::distribution_point> e1(
+ DPL::FromUTF8String(cached_data->distribution_point));
+
+ select->Where(e1);
+ std::list<CRLResponseStorage::Row> rows = select->GetRowList();
+ if (1 == rows.size()) {
+ CRLResponseStorage::Row row = rows.front();
+ cached_data->crl_body = DPL::ToUTF8String(row.Get_crl_body());
+ cached_data->next_update_time = *(row.Get_next_update_time());
+ return true;
+ }
+
+ LogDebug("Cached CRL not found");
+ return false;
+ }
+ Catch(DPL::DB::SqlConnection::Exception::Base) {
+ ReThrowMsg(Exception::DatabaseError, "Failed to getCRLResponse");
+ }
+}
+
+void CertificateCacheDAO::getCRLResponseList(
+ CRLCachedDataList* cached_data_list)
+{
+ if (NULL == cached_data_list) {
+ LogError("NULL pointer");
+ return;
+ }
+ Try {
+ VCORE_DB_SELECT(select, CRLResponseStorage, &ThreadInterface())
+ typedef std::list<CRLResponseStorage::Row> RowList;
+ RowList list = select->GetRowList();
+
+ FOREACH(i, list) {
+ CRLCachedData response;
+ response.distribution_point = DPL::ToUTF8String(
+ i->Get_distribution_point());
+ response.crl_body = DPL::ToUTF8String(i->Get_crl_body());
+ response.next_update_time = *(i->Get_next_update_time());
+ cached_data_list->push_back(response);
+ }
+
+ }
+ Catch(DPL::DB::SqlConnection::Exception::Base) {
+ ReThrowMsg(Exception::DatabaseError, "Failed to getCRLResponses");
+ }
+}
+
+void CertificateCacheDAO::clearCertificateCache()
+{
+ Try {
+ ScopedTransaction transaction(&ThreadInterface());
+ VCORE_DB_DELETE(del1, OCSPResponseStorage, &ThreadInterface())
+ del1->Execute();
+ VCORE_DB_DELETE(del2, CRLResponseStorage, &ThreadInterface())
+ del2->Execute();
+ transaction.Commit();
+ }
+ Catch(DPL::DB::SqlConnection::Exception::Base) {
+ ReThrowMsg(Exception::DatabaseError, "Failed to clearUserSettings");
+ }
+}
+
+VerificationStatus CertificateCacheDAO::intToVerificationStatus(int p)
+{
+ switch (p) {
+ case 1:
+ return VERIFICATION_STATUS_GOOD;
+ case 1 << 1:
+ return VERIFICATION_STATUS_REVOKED;
+ case 1 << 2:
+ return VERIFICATION_STATUS_UNKNOWN;
+ case 1 << 3:
+ return VERIFICATION_STATUS_VERIFICATION_ERROR;
+ case 1 << 4:
+ return VERIFICATION_STATUS_NOT_SUPPORT;
+ case 1 << 5:
+ return VERIFICATION_STATUS_CONNECTION_FAILED;
+ case 1 << 6:
+ return VERIFICATION_STATUS_ERROR;
+ default:
+ return VERIFICATION_STATUS_ERROR;
+ }
+}
+
+} // namespace ValidationCore
--- /dev/null
+/*
+ * 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 CertificateCacheDAO.h
+ * @author Tomasz Swierczek (t.swierczek@samsung.com)
+ * @version 0.1
+ * @brief Header file for class managing CRL and OCSP cached responses
+ */
+
+#ifndef _WRT_SRC_CONFIGURATION_CERTIFICATE_CACHE_DAO_H_
+#define _WRT_SRC_CONFIGURATION_CERTIFICATE_CACHE_DAO_H_
+
+#include <string>
+#include <list>
+
+#include <dpl/exception.h>
+
+#include <vcore/VerificationStatus.h>
+#include <vcore/CRLCacheInterface.h>
+
+namespace ValidationCore {
+
+struct OCSPCachedStatus
+{
+ std::string cert_chain;
+ VerificationStatus ocsp_status;
+ bool end_entity_check;
+ time_t next_update_time;
+};
+
+typedef std::list<OCSPCachedStatus> OCSPCachedStatusList;
+
+typedef std::list<CRLCachedData> CRLCachedDataList;
+
+class CertificateCacheDAO {
+ public:
+ class Exception
+ {
+ public:
+ DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
+ DECLARE_EXCEPTION_TYPE(Base, DatabaseError)
+ };
+
+ // OCSP statuses
+
+ static void setOCSPStatus(const std::string& cert_chain,
+ VerificationStatus ocsp_status,
+ bool end_entity_check,
+ time_t next_update_time);
+
+ /*
+ * fill cert_chain and end_entity_check in cached_status
+ * returns true iff cached status found without errors
+ */
+ static bool getOCSPStatus(OCSPCachedStatus* cached_status);
+ static void getOCSPStatusList(OCSPCachedStatusList* cached_status_list);
+
+ // CRL responses
+
+ static void setCRLResponse(const std::string& distribution_point,
+ const std::string& crl_body,
+ time_t next_update_time);
+ static void setCRLResponse(CRLCachedData *ptr) {
+ setCRLResponse(
+ ptr->distribution_point,
+ ptr->crl_body,
+ ptr->next_update_time);
+ }
+ /*
+ * fill distribution_point
+ * returns true iff cached list for dist. point found without errors
+ */
+ static bool getCRLResponse(CRLCachedData* cached_data);
+ static void getCRLResponseList(CRLCachedDataList* cached_data_list);
+
+
+ // clears CRL and OCSP cached data
+ static void clearCertificateCache();
+
+ private:
+
+ static VerificationStatus intToVerificationStatus(int p);
+
+ CertificateCacheDAO()
+ {
+ }
+};
+
+} // namespace ValidationCore
+
+#endif /* _WRT_SRC_CONFIGURATION_CERTIFICATE_CACHE_DAO_H_ */
--- /dev/null
+/*
+ * 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 CertificateCollection.cpp
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 0.1
+ * @brief
+ */
+#include <vcore/CertificateCollection.h>
+
+#include <algorithm>
+
+#include <dpl/binary_queue.h>
+#include <dpl/foreach.h>
+#include <dpl/log/log.h>
+
+#include <vcore/Base64.h>
+
+namespace {
+
+using namespace ValidationCore;
+
+inline std::string toBinaryString(int data)
+{
+ char buffer[sizeof(int)];
+ memcpy(buffer, &data, sizeof(int));
+ return std::string(buffer, buffer + sizeof(int));
+}
+
+} // namespace
+
+namespace ValidationCore {
+
+CertificateCollection::CertificateCollection()
+ : m_collectionStatus(COLLECTION_UNSORTED)
+{}
+
+void CertificateCollection::clear(void)
+{
+ m_collectionStatus = COLLECTION_UNSORTED;
+ m_certList.clear();
+}
+
+void CertificateCollection::load(const CertificateList &certList)
+{
+ m_collectionStatus = COLLECTION_UNSORTED;
+ std::copy(certList.begin(),
+ certList.end(),
+ std::back_inserter(m_certList));
+}
+
+bool CertificateCollection::load(const std::string &buffer)
+{
+ Base64Decoder base64;
+ base64.reset();
+ base64.append(buffer);
+ if (!base64.finalize()) {
+ LogWarning("Error during chain decoding");
+ return false;
+ }
+ std::string binaryData = base64.get();
+
+ DPL::BinaryQueue queue;
+ queue.AppendCopy(binaryData.c_str(), binaryData.size());
+
+ int certNum;
+ queue.FlattenConsume(&certNum, sizeof(int));
+
+ CertificateList list;
+
+ for (int i = 0; i < certNum; ++i) {
+ int certSize;
+ queue.FlattenConsume(&certSize, sizeof(int));
+ std::vector<char> rawDERCert;
+ rawDERCert.resize(certSize);
+ queue.FlattenConsume(&rawDERCert[0], certSize);
+ Try {
+ list.push_back(CertificatePtr(
+ new Certificate(std::string(rawDERCert.begin(),
+ rawDERCert.end()))));
+ } Catch(Certificate::Exception::Base) {
+ LogWarning("Error during certificate creation.");
+ return false;
+ }
+ LogDebug("Loading certificate. Certificate common name: " <<
+ list.back()->getCommonName());
+ }
+ load(list);
+ return true;
+}
+
+std::string CertificateCollection::toBase64String() const
+{
+ std::ostringstream output;
+ int certNum = m_certList.size();
+ output << toBinaryString(certNum);
+ FOREACH(i, m_certList){
+ std::string derCert = (*i)->getDER();
+ output << toBinaryString(derCert.size());
+ output << derCert;
+ }
+ Base64Encoder base64;
+ base64.reset();
+ base64.append(output.str());
+ base64.finalize();
+ return base64.get();
+}
+
+CertificateList CertificateCollection::getCertificateList() const
+{
+ return m_certList;
+}
+
+bool CertificateCollection::isChain() const
+{
+ if (COLLECTION_SORTED != m_collectionStatus) {
+ LogError("You must sort certificates first");
+ ThrowMsg(Exception::WrongUsage,
+ "You must sort certificates first");
+ }
+ return (COLLECTION_SORTED == m_collectionStatus) ? true : false;
+}
+
+bool CertificateCollection::sort()
+{
+ if (COLLECTION_UNSORTED == m_collectionStatus) {
+ sortCollection();
+ }
+ return (COLLECTION_SORTED == m_collectionStatus) ? true : false;
+}
+
+CertificateList CertificateCollection::getChain() const
+{
+ if (COLLECTION_SORTED != m_collectionStatus) {
+ LogError("You must sort certificates first");
+ ThrowMsg(Exception::WrongUsage,
+ "You must sort certificates first");
+ }
+ return m_certList;
+}
+
+void CertificateCollection::sortCollection()
+{
+ // sorting is not necessary
+ if (m_certList.empty()) {
+ m_collectionStatus = COLLECTION_SORTED;
+ return;
+ }
+
+ CertificateList sorted;
+ std::map<std::string, CertificatePtr> subTransl;
+ std::map<std::string, CertificatePtr> issTransl;
+
+ // Sort all certificate by subject
+ for (auto it = m_certList.begin(); it != m_certList.end(); ++it) {
+ subTransl.insert(std::make_pair(DPL::ToUTF8String((*it)->getOneLine()),(*it)));
+ }
+ // We need one start certificate
+ sorted.push_back(subTransl.begin()->second);
+ subTransl.erase(subTransl.begin());
+
+ // Get the issuer from front certificate and find certificate with this subject in subTransl.
+ // Add this certificate to the front.
+ while (!subTransl.empty()) {
+ std::string issuer = DPL::ToUTF8String(sorted.back()->getOneLine(Certificate::FIELD_ISSUER));
+ auto it = subTransl.find(issuer);
+ if (it == subTransl.end()) {
+ break;
+ }
+ sorted.push_back(it->second);
+ subTransl.erase(it);
+ }
+
+ // Sort all certificates by issuer
+ for (auto it = subTransl.begin(); it != subTransl.end(); ++it) {
+ issTransl.insert(std::make_pair(DPL::ToUTF8String((it->second->getOneLine(Certificate::FIELD_ISSUER))),it->second));
+ }
+
+ // Get the subject from last certificate and find certificate with such issuer in issTransl.
+ // Add this certificate at end.
+ while (!issTransl.empty()) {
+ std::string sub = DPL::ToUTF8String(sorted.front()->getOneLine());
+ auto it = issTransl.find(sub);
+ if (it == issTransl.end()) {
+ break;
+ }
+ sorted.push_front(it->second);
+ issTransl.erase(it);
+ }
+
+ if (!issTransl.empty()) {
+ LogWarning("Certificates don't form a valid chain.");
+ m_collectionStatus = COLLECTION_CHAIN_BROKEN;
+ return;
+ }
+
+ m_collectionStatus = COLLECTION_SORTED;
+ m_certList = sorted;
+}
+
+size_t CertificateCollection::size() const {
+ return m_certList.size();
+}
+
+bool CertificateCollection::empty() const {
+ return m_certList.empty();
+}
+
+CertificateCollection::const_iterator CertificateCollection::begin() const {
+ return m_certList.begin();
+}
+
+CertificateCollection::const_iterator CertificateCollection::end() const {
+ return m_certList.end();
+}
+
+CertificatePtr CertificateCollection::back() const {
+ return m_certList.back();
+}
+
+} // namespace ValidationCore
+
--- /dev/null
+/*
+ * 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 CertificateCollection.h
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 0.1
+ * @brief
+ */
+#ifndef _VALIDATION_CORE_CERTIFICATECOLLECTION_H_
+#define _VALIDATION_CORE_CERTIFICATECOLLECTION_H_
+
+#include <list>
+#include <string>
+
+#include <dpl/exception.h>
+
+#include <vcore/Certificate.h>
+
+namespace ValidationCore {
+/*
+ * This class is used to store Certificate Chain.
+ * It could serialize chain to std::string in base64 form.
+ * It could read chain written in base64 form.
+ * It could check if collection creates certificate chain.
+ */
+
+class CertificateCollection
+{
+ public:
+ class Exception
+ {
+ public:
+ DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
+ DECLARE_EXCEPTION_TYPE(Base, WrongUsage)
+ };
+
+ CertificateCollection();
+
+ typedef CertificateList::const_iterator const_iterator;
+
+ /*
+ * Remove all certificates from collection.
+ */
+ void clear();
+
+ /*
+ * In current implemenation this function MUST success.
+ *
+ * This function will add new certificate to collection.
+ * This function DOES NOT clean collection.
+ */
+ void load(const CertificateList &certList);
+
+ /*
+ * This function will return false if base64 string is broken
+ * (is not encoded in base64 format) or one from certificate
+ * is broken (is not encoded in der format).
+ *
+ * This function will add new certificate to collection.
+ * This function DOES NOT clean collection.
+ */
+ bool load(const std::string &base64);
+
+ /*
+ * This function will return all certificates from
+ * collection encoded in base64 format.
+ */
+ std::string toBase64String() const;
+
+ /*
+ * This will return all certificate from collection.
+ */
+ CertificateList getCertificateList() const;
+
+ /*
+ * This function will return true if certificates
+ * in in this structure were sorted and create
+ * certificate chain.
+
+ * Note: You MUST sort certificates first.
+ */
+ bool isChain() const;
+
+ /*
+ * This function will return true if all certificate are
+ * able to create certificate chain.
+ *
+ * This function will sort certificates if collection
+ * is not sorted.
+ *
+ * Note: This function will make all iterators invalid.
+ */
+ bool sort();
+
+ /*
+ * This function will return Certificate chain.
+ *
+ * First certificate on the list is EndEntity certificate.
+ *
+ * Last certificate on the list is RootCA certificate or
+ * CA certificate if RootCA is not present.
+ *
+ * Note: You MUST sort certificates first and
+ * check if certificates creates proper chain.
+ */
+ CertificateList getChain() const;
+
+ /*
+ * It returns size of certificate collection.
+ */
+ size_t size() const;
+
+ /*
+ * Return true if collection is empty.
+ */
+ bool empty() const;
+
+ /*
+ * This will return end iterator to internal collection.
+ *
+ * Note: this iterator will lose validity if you call non const
+ * method on CertificateCollection class.
+ */
+ const_iterator begin() const;
+
+ /*
+ * This will return end iterator to internal collection.
+ *
+ * Note: this iterator will lose validity if you call non const
+ * method on CertificateCollection class.
+ */
+ const_iterator end() const;
+
+ /*
+ * This function will return the last certificate from collection.
+ *
+ * Note: There is no point to call this function if certificate
+ * collection is not sorted!
+ */
+ CertificatePtr back() const;
+
+ protected:
+ void sortCollection(void);
+
+ enum CollectionStatus
+ {
+ // Certificate collection are not sorted in any way
+ COLLECTION_UNSORTED,
+ // Certificate collection creates certificate chain
+ COLLECTION_SORTED,
+ // Cerfificate collection is not able to create certificate chain
+ COLLECTION_CHAIN_BROKEN,
+ };
+
+ CollectionStatus m_collectionStatus;
+ CertificateList m_certList;
+};
+
+typedef std::list<CertificateCollection> CertificateCollectionList;
+
+} // namespace ValidationCore
+
+#endif // _VALIDATION_CORE_CERTIFICATECHAIN_H_
--- /dev/null
+/*
+ * 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
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief
+ */
+#include "CertificateConfigReader.h"
+
+#include <cstdlib>
+
+#include <dpl/assert.h>
+
+namespace {
+const std::string XML_EMPTY_NAMESPACE = "";
+
+const std::string TOKEN_CERTIFICATE_SET = "CertificateSet";
+const std::string TOKEN_CERTIFICATE_DOMAIN = "CertificateDomain";
+const std::string TOKEN_FINGERPRINT_SHA1 = "FingerprintSHA1";
+
+const std::string TOKEN_ATTR_NAME = "name";
+const std::string TOKEN_VALUE_WAC_ROOT = "wacroot";
+const std::string TOKEN_VALUE_WAC_PUBLISHER = "wacpublisher";
+const std::string TOKEN_VALUE_WAC_MEMBER = "wacmember";
+const std::string TOKEN_VALUE_DEVELOPER = "developer";
+const std::string TOKEN_VALUE_TIZEN_MEMBER = "tizenmember";
+const std::string TOKEN_VALUE_ORANGE_LEGACY = "orangelegacy";
+
+int hexCharToInt(char c)
+{
+ if (c >= 'a' && c <= 'f') {
+ return 10 + static_cast<int>(c) - 'a';
+ }
+ if (c >= 'A' && c <= 'F') {
+ return 10 + static_cast<int>(c) - 'A';
+ }
+ if (c >= '0' && c <= '9') {
+ return static_cast<int>(c) - '0';
+ }
+ return c;
+}
+} // anonymous namespace
+
+namespace ValidationCore {
+CertificateConfigReader::CertificateConfigReader() :
+ m_certificateDomain(0),
+ m_parserSchema(this)
+{
+ m_parserSchema.addBeginTagCallback(
+ TOKEN_CERTIFICATE_SET,
+ XML_EMPTY_NAMESPACE,
+ &CertificateConfigReader::blankFunction);
+
+ m_parserSchema.addBeginTagCallback(
+ TOKEN_CERTIFICATE_DOMAIN,
+ XML_EMPTY_NAMESPACE,
+ &CertificateConfigReader::tokenCertificateDomain);
+
+ m_parserSchema.addBeginTagCallback(
+ TOKEN_FINGERPRINT_SHA1,
+ XML_EMPTY_NAMESPACE,
+ &CertificateConfigReader::blankFunction);
+
+ m_parserSchema.addEndTagCallback(
+ TOKEN_CERTIFICATE_SET,
+ XML_EMPTY_NAMESPACE,
+ &CertificateConfigReader::blankFunction);
+
+ m_parserSchema.addEndTagCallback(
+ TOKEN_CERTIFICATE_DOMAIN,
+ XML_EMPTY_NAMESPACE,
+ &CertificateConfigReader::blankFunction);
+
+ m_parserSchema.addEndTagCallback(
+ TOKEN_FINGERPRINT_SHA1,
+ XML_EMPTY_NAMESPACE,
+ &CertificateConfigReader::tokenEndFingerprintSHA1);
+}
+
+void CertificateConfigReader::tokenCertificateDomain(CertificateIdentifier &)
+{
+ std::string name = m_parserSchema.getReader().
+ attribute(TOKEN_ATTR_NAME, SaxReader::THROW_DISABLE);
+
+ if (name.empty()) {
+ LogWarning("Invalid fingerprint file. Domain name is mandatory");
+ ThrowMsg(Exception::InvalidFile,
+ "Invalid fingerprint file. Domain name is mandatory");
+ } else if (name == TOKEN_VALUE_DEVELOPER) {
+ m_certificateDomain = CertStoreId::DEVELOPER;
+ } else if (name == TOKEN_VALUE_WAC_ROOT) {
+ m_certificateDomain = CertStoreId::WAC_ROOT;
+ } else if (name == TOKEN_VALUE_WAC_PUBLISHER) {
+ m_certificateDomain = CertStoreId::WAC_PUBLISHER;
+ } else if (name == TOKEN_VALUE_WAC_MEMBER) {
+ m_certificateDomain = CertStoreId::WAC_MEMBER;
+ } else if (name == TOKEN_VALUE_TIZEN_MEMBER) {
+ m_certificateDomain = CertStoreId::TIZEN_MEMBER;
+ } else if (name == TOKEN_VALUE_ORANGE_LEGACY) {
+ m_certificateDomain = CertStoreId::ORANGE_LEGACY;
+ } else {
+ LogWarning("This domain will be ignored: " << name);
+ m_certificateDomain = 0;
+ }
+}
+
+void CertificateConfigReader::tokenEndFingerprintSHA1(
+ CertificateIdentifier &identificator)
+{
+ std::string text = m_parserSchema.getText();
+ text += ":"; // add guard at the end of fingerprint
+ Certificate::Fingerprint fingerprint;
+ int s = 0;
+ int byteDescLen = 0;
+ for (size_t i = 0; i < text.size(); ++i) {
+ if (isxdigit(text[i])) {
+ s <<= 4;
+ s += hexCharToInt(text[i]);
+ byteDescLen++;
+ if (byteDescLen > 2) {
+ Assert(0 && "Unsupported fingerprint format in xml file.");
+ }
+ } else if (text[i] == ':') {
+ fingerprint.push_back(static_cast<unsigned char>(s));
+ s = 0;
+ byteDescLen = 0;
+ } else {
+ Assert(0 && "Unussported fingerprint format in xml file.");
+ }
+ }
+ identificator.add(fingerprint, m_certificateDomain);
+}
+} // namespace ValidationCore
--- /dev/null
+/*
+ * 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 CertificateConfigReader.h
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief
+ */
+#ifndef _VALIDATION_CORE_CERTIFICATE_CONFIG_READER_H_
+#define _VALIDATION_CORE_CERTIFICATE_CONFIG_READER_H_
+
+#include <string>
+#include <dpl/exception.h>
+
+#include <vcore/CertificateIdentifier.h>
+#include <vcore/CertStoreType.h>
+#include <vcore/ParserSchema.h>
+
+namespace ValidationCore {
+class CertificateConfigReader
+{
+ public:
+ class Exception
+ {
+ public:
+ DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
+ DECLARE_EXCEPTION_TYPE(Base, InvalidFile)
+ };
+ CertificateConfigReader();
+
+ void initialize(const std::string &file,
+ const std::string &scheme)
+ {
+ m_parserSchema.initialize(file, true, SaxReader::VALIDATION_XMLSCHEME,
+ scheme);
+ }
+
+ void read(CertificateIdentifier &identificator)
+ {
+ m_parserSchema.read(identificator);
+ }
+
+ private:
+ void blankFunction(CertificateIdentifier &)
+ {
+ }
+ void tokenCertificateDomain(CertificateIdentifier &identificator);
+ void tokenEndFingerprintSHA1(CertificateIdentifier &identificator);
+
+ CertStoreId::Type m_certificateDomain;
+ ParserSchema<CertificateConfigReader, CertificateIdentifier>
+ m_parserSchema;
+};
+} // namespace ValidationCore
+
+#endif // _VALIDATION_CORE_CERTIFICATE_CONFIG_READER_H_
--- /dev/null
+/*
+ * 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
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief
+ */
+#ifndef \
+ _WRT_ENGINE_SRC_INSTALLER_CORE_VALIDATION_CORE_CERTIFICATEIDENTIFICATOR_H_
+#define \
+ _WRT_ENGINE_SRC_INSTALLER_CORE_VALIDATION_CORE_CERTIFICATEIDENTIFICATOR_H_
+
+#include <map>
+
+#include <dpl/noncopyable.h>
+
+#include "Certificate.h"
+#include "CertStoreType.h"
+
+namespace ValidationCore {
+class CertificateIdentifier : public DPL::Noncopyable
+{
+ public:
+ typedef std::map<Certificate::Fingerprint, CertStoreId::Set> FingerPrintMap;
+
+ CertificateIdentifier()
+ {
+ }
+ ~CertificateIdentifier()
+ {
+ }
+
+ void add(const Certificate::Fingerprint &fingerprint,
+ CertStoreId::Type domain)
+ {
+ fingerPrintMap[fingerprint].add(domain);
+ }
+
+ CertStoreId::Set find(const Certificate::Fingerprint &fingerprint) const
+ {
+ FingerPrintMap::const_iterator iter = fingerPrintMap.find(fingerprint);
+ if (iter == fingerPrintMap.end()) {
+ return CertStoreId::Set();
+ }
+ return iter->second;
+ }
+
+ CertStoreId::Set find(const CertificatePtr &certificate) const
+ {
+ return
+ find(certificate->getFingerprint(Certificate::FINGERPRINT_SHA1));
+ }
+
+ private:
+ FingerPrintMap fingerPrintMap;
+};
+} // namespace ValidationCore
+
+#endif // _WRT_ENGINE_SRC_INSTALLER_CORE_VALIDATION_CORE_CERTIFICATEIDENTIFICATOR_H_
--- /dev/null
+/*
+ * 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.
+ */
+#include <dpl/assert.h>
+#include <openssl/x509v3.h>
+#include <dpl/log/log.h>
+#include <dpl/noncopyable.h>
+#include <openssl/ecdsa.h>
+#include <openssl/evp.h>
+
+#include <vcore/Base64.h>
+#include <vcore/CertificateLoader.h>
+#include <vcore/SSLContainers.h>
+
+namespace {
+const int MIN_RSA_KEY_LENGTH = 1024;
+//const char *OID_CURVE_SECP256R1 = "urn:oid:1.2.840.10045.3.1.7";
+} // namespace anonymous
+
+namespace ValidationCore {
+//// COMPARATOR CLASS START ////
+
+//class CertificateLoaderECDSA : public CertificateLoader::CertificateLoaderComparator, DPL::Noncopyable {
+//public:
+// CertificateLoaderECDSA(const std::string &publicKey)
+// : m_ecPublicKey(NULL)
+// , m_searchKey(NULL)
+// {
+// m_bnCtx = BN_CTX_new(); // if fails we can continue anyway
+// m_tmpPoint = BN_new(); // if fails we can continue anyway
+// m_initialized = CertificateLoader::convertBase64NodeToBigNum(publicKey, &m_searchKey);
+//
+// if(!m_initialized)
+// LogError("Init failed!");
+// }
+//
+// virtual bool compare(X509 *x509cert){
+// if(!m_initialized)
+// return false;
+//
+// EVP_PKEY_free(m_ecPublicKey);
+//
+// m_ecPublicKey = X509_get_pubkey(x509cert);
+//
+// if(m_ecPublicKey == NULL)
+// return false;
+//
+// if(m_ecPublicKey->type != EVP_PKEY_EC){
+// LogError("ecPublicKey has wrong type!");
+// return false;
+// }
+//
+// // Pointer to internal data of ecPublicKey. Do not free!
+// EC_KEY *eckey = m_ecPublicKey->pkey.ec;
+//
+// const EC_POINT *ecpoint = EC_KEY_get0_public_key(eckey);
+// const EC_GROUP *ecgroup = EC_KEY_get0_group(eckey);
+//
+// m_tmpPoint = EC_POINT_point2bn(ecgroup, ecpoint, POINT_CONVERSION_UNCOMPRESSED, m_tmpPoint, m_bnCtx);
+//
+// if(BN_cmp(m_tmpPoint, m_searchKey) == 0)
+// return true;
+//
+// return false;
+// }
+//
+// ~CertificateLoaderECDSA(){
+// BN_CTX_free(m_bnCtx);
+// EVP_PKEY_free(m_ecPublicKey);
+// BN_free(m_searchKey);
+// BN_free(m_tmpPoint);
+// }
+//
+//private:
+// bool m_initialized;
+// EVP_PKEY *m_ecPublicKey;
+// BN_CTX *m_bnCtx;
+// BIGNUM *m_searchKey;
+// BIGNUM *m_tmpPoint;
+//};
+
+///// COMPARETORS CLASS END /////
+
+//// COMPARATOR RSA CLASS START ////
+
+//class CertificateLoaderRSA : public CertificateLoader::CertificateLoaderComparator, DPL::Noncopyable {
+//public:
+// CertificateLoaderRSA(const std::string &m_modulus,const std::string &m_exponent )
+// : m_rsaPublicKey(NULL)
+// , m_modulus_bn(NULL)
+// , m_exponent_bn(NULL)
+// {
+//
+// m_initialized_modulus = CertificateLoader::convertBase64NodeToBigNum(m_modulus, &m_modulus_bn);
+// m_initialized_exponent = CertificateLoader::convertBase64NodeToBigNum(m_exponent, &m_exponent_bn);
+//
+// if(!m_initialized_modulus || !m_initialized_exponent)
+// LogError("Init failed!");
+// }
+//
+// virtual bool compare(X509 *x509cert){
+//
+// if(!m_initialized_modulus || !m_initialized_exponent)
+// return false;
+//
+// EVP_PKEY_free(m_rsaPublicKey);
+// m_rsaPublicKey = X509_get_pubkey(x509cert);
+//
+// if(m_rsaPublicKey == NULL)
+// return false;
+//
+// if(m_rsaPublicKey->type != EVP_PKEY_RSA){
+// LogInfo("rsaPublicKey has wrong type!");
+// return false;
+// }
+//
+// RSA *rsa = NULL;
+// rsa = m_rsaPublicKey->pkey.rsa;
+//
+// if (BN_cmp(m_modulus_bn, rsa->n) == 0 &&
+// BN_cmp(m_exponent_bn, rsa->e) == 0 ){
+// LogError ("Compare TRUE");
+// return true;
+// }
+// return false;
+// }
+//
+// ~CertificateLoaderRSA(){
+// EVP_PKEY_free(m_rsaPublicKey);
+// BN_free(m_modulus_bn);
+// BN_free(m_exponent_bn);
+//
+// }
+//
+//private:
+// bool m_initialized_modulus;
+// bool m_initialized_exponent;
+// EVP_PKEY *m_rsaPublicKey;
+// BIGNUM *m_modulus_bn;
+// BIGNUM *m_exponent_bn;
+//};
+
+///// COMPARETORS RSA CLASS END /////
+
+CertificateLoader::CertificateLoaderResult CertificateLoader::
+ loadCertificateBasedOnExponentAndModulus(const std::string &m_modulus,
+ const std::string &m_exponent)
+{
+ (void) m_modulus;
+ (void) m_exponent;
+ LogError("Not implemented.");
+ return UNKNOWN_ERROR;
+ // if (m_exponent.empty() || m_modulus.empty())
+ // return WRONG_ARGUMENTS;
+ //
+ // CertificateLoaderRSA comparator(m_modulus,m_exponent);
+ //
+ // CertificateLoaderResult result = NO_ERROR;
+ // for(int i=0; storeId[i]; ++i){
+ // result = loadCertificate(std::string(storeId[i]), &comparator);
+ //
+ // if(result == ERR_NO_MORE_CERTIFICATES)
+ // continue;
+ //
+ // return result;
+ // }
+ //
+ // return result;
+}
+
+CertificateLoader::CertificateLoaderResult CertificateLoader::loadCertificate(
+ const std::string &storageName,
+ CertificateLoader::CertificateLoaderComparator *cmp)
+{
+ (void) storageName;
+ (void) cmp;
+ LogError("Not Implemented");
+ return UNKNOWN_ERROR;
+ // long int result = OPERATION_SUCCESS;
+ //
+ // char storeId[CERTMGR_MAX_PLUGIN_ID_SIZE];
+ // char type[CERTMGR_MAX_CERT_TYPE_SIZE];
+ // certmgr_cert_id certId;
+ // certmgr_ctx context;
+ // certmgr_mem_buff certRetrieved;
+ // unsigned char buffer[CERTMGR_MAX_BUFFER_SIZE];
+ //
+ // certmgr_cert_descriptor descriptor;
+ //
+ // certRetrieved.data = buffer;
+ // certRetrieved.firstFree = 0;
+ // certRetrieved.size = CERTMGR_MAX_BUFFER_SIZE;
+ // certId.storeId = storeId;
+ // certId.type = type;
+ //
+ // CERTMGR_INIT_CONTEXT((&context), (sizeof(context)))
+ //
+ // strncpy(context.storeId, storageName.c_str(), storageName.size());
+ //
+ // for(certRetrieved.firstFree = 0;
+ // OPERATION_SUCCESS == (result = certmgr_retrieve_certificate_from_store(&context, &certRetrieved, &certId));
+ // certRetrieved.firstFree = 0)
+ // {
+ //
+ // if(OPERATION_SUCCESS!=certmgr_extract_certificate_data(&certRetrieved, &descriptor)){
+ // LogError("Extracting Certificate Data failed \n");
+ // continue;
+ // }
+ //
+ // const unsigned char *ptr = certRetrieved.data;
+ //
+ // X509 *x509cert = d2i_X509(NULL, &ptr, certRetrieved.size);
+ // if(x509cert == NULL){
+ // certmgr_release_certificate_data(&descriptor);
+ // LogError("Error extracting certificate (d2i_X509).");
+ // return UNKNOWN_ERROR;
+ // }
+ //
+ // LogDebug("The subject of this certificate is " << descriptor.mandatory.subject);
+ // if(cmp->compare(x509cert)){
+ // LogDebug("Found match. Coping bytes: " << certRetrieved.size);
+ // m_certificatePtr = CertificatePtr(new Certificate(certRetrieved));
+ // certmgr_release_certificate_data(&descriptor);
+ // X509_free(x509cert);
+ // break;
+ // }
+ //
+ // LogDebug("Release");
+ // X509_free(x509cert);
+ // certmgr_release_certificate_data(&descriptor);
+ // }
+ //
+ // if(ERR_NO_MORE_CERTIFICATES == result){
+ // LogError("Certificates for given DN not found\n");
+ // return CERTIFICATE_NOT_FOUND;
+ // }
+ //
+ // if(result!= OPERATION_SUCCESS){
+ // LogError("Certificate Manager Error\n");
+ // return UNKNOWN_ERROR;
+ // }
+ //
+ // LogDebug("Exit");
+ // return NO_ERROR;
+}
+
+// TODO
+CertificateLoader::CertificateLoaderResult CertificateLoader::
+ loadCertificateBasedOnSubjectName(const std::string &subjectName)
+{
+ (void) subjectName;
+ LogError("Not implemented.");
+ return UNKNOWN_ERROR;
+ // if(subjectName.empty())
+ // {
+ // return WRONG_ARGUMENTS;
+ // }
+ //
+ // long int result = OPERATION_SUCCESS;
+ //
+ // char storeId[CERTMGR_MAX_PLUGIN_ID_SIZE];
+ // char type[CERTMGR_MAX_CERT_TYPE_SIZE];
+ // certmgr_cert_id certId;
+ // certmgr_ctx context;
+ // certmgr_mem_buff certRetrieved;
+ // unsigned char buffer[CERTMGR_MAX_BUFFER_SIZE];
+ //
+ // certmgr_cert_descriptor descriptor;
+ //
+ // certRetrieved.data = buffer;
+ // certRetrieved.firstFree = 0;
+ // certRetrieved.size = CERTMGR_MAX_BUFFER_SIZE;
+ // certId.storeId = storeId;
+ // certId.type = type;
+ //
+ // CERTMGR_INIT_CONTEXT((&context), (sizeof(context)))
+ //
+ // for(certRetrieved.firstFree = 0;
+ // OPERATION_SUCCESS == (result = certmgr_retrieve_certificate_from_store(&context, &certRetrieved, &certId));
+ // certRetrieved.firstFree = 0)
+ // {
+ //
+ // if(OPERATION_SUCCESS!=certmgr_extract_certificate_data(&certRetrieved, &descriptor)){
+ // LogError("Extracting Certificate Data failed \n");
+ // continue;
+ // }
+ //
+ // if(!strcmp(subjectName.c_str(), descriptor.mandatory.subject)){
+ // LogDebug("The subject of this certificate is " << descriptor.mandatory.subject);
+ // m_certificatePtr = CertificatePtr(new Certificate(certRetrieved));
+ // certmgr_release_certificate_data(&descriptor);
+ // break;
+ // }
+ // LogDebug("Release");
+ // certmgr_release_certificate_data(&descriptor);
+ // }
+ //
+ // if(ERR_NO_MORE_CERTIFICATES == result) {
+ // LogError("Certificates for given DN not found\n");
+ // return CERTIFICATE_NOT_FOUND;
+ // }
+ // if(result!= OPERATION_SUCCESS){
+ // LogError("Certificate Manager Error\n");
+ // return UNKNOWN_ERROR;
+ // }
+ // LogDebug("Exit");
+ // return NO_ERROR;
+}
+
+// KW CertificateLoader::CertificateLoaderResult CertificateLoader::loadCertificateBasedOnIssuerName(const std::string &issuerName, const std::string &serialNumber)
+// KW {
+// KW if(issuerName.empty() || serialNumber.empty())
+// KW {
+// KW return WRONG_ARGUMENTS;
+// KW }
+// KW
+// KW if(m_cmBuff.data){
+// KW delete[] m_cmBuff.data;
+// KW memset(&m_cmBuff, 0, sizeof(certmgr_mem_buff));
+// KW }
+// KW
+// KW LogDebug("IssuerName: " << issuerName << " serialNumber: " << serialNumber);
+// KW
+// KW //used to check status of retrieved certificate
+// KW long int result = OPERATION_SUCCESS;
+// KW char storeId[CERTMGR_MAX_PLUGIN_ID_SIZE];
+// KW char type[CERTMGR_MAX_CERT_TYPE_SIZE];
+// KW certmgr_cert_id certId;
+// KW certmgr_ctx context;
+// KW certmgr_mem_buff certRetrieved;
+// KW unsigned char buffer[CERTMGR_MAX_BUFFER_SIZE];
+// KW
+// KW certmgr_cert_descriptor descriptor;
+// KW
+// KW certRetrieved.data = buffer;
+// KW certRetrieved.firstFree = 0;
+// KW certRetrieved.size = CERTMGR_MAX_BUFFER_SIZE;
+// KW certId.storeId = storeId;
+// KW certId.type = type;
+// KW
+// KW CERTMGR_INIT_CONTEXT((&context), (sizeof(context)))
+// KW
+// KW for(certRetrieved.firstFree = 0;
+// KW OPERATION_SUCCESS == (result = certmgr_retrieve_certificate_from_store(&context, &certRetrieved, &certId));
+// KW certRetrieved.firstFree = 0)
+// KW {
+// KW
+// KW LogDebug("Extracting certificate from CertMgr");
+// KW
+// KW if( OPERATION_SUCCESS != certmgr_extract_certificate_data(&certRetrieved, &descriptor) ){
+// KW LogError("Extracting Certificate Data failed \n");
+// KW continue;
+// KW }
+// KW
+// KW LogDebug("Issuer: " << descriptor.mandatory.issuer);
+// KW
+// KW const unsigned char *ptr = certRetrieved.data;
+// KW char *tmp;
+// KW
+// KW X509 *x509cert = d2i_X509(NULL, &ptr, certRetrieved.size);
+// KW std::string serialNO = std::string(tmp = i2s_ASN1_INTEGER(NULL, X509_get_serialNumber(x509cert)));
+// KW OPENSSL_free(tmp);
+// KW X509_free(x509cert);
+// KW
+// KW LogInfo("Certificate number found: " << serialNO);
+// KW LogInfo("Certificate number looking for: " << serialNumber);
+// KW
+// KW if(!strcmp(issuerName.c_str(), descriptor.mandatory.issuer)
+// KW && serialNumber == serialNO)
+// KW {
+// KW LogError("The issuer of this certificate is " << descriptor.mandatory.issuer);
+// KW
+// KW m_cmBuff.data = new unsigned char[certRetrieved.size];
+// KW m_cmBuff.firstFree = m_cmBuff.size = certRetrieved.size;
+// KW memcpy(m_cmBuff.data, certRetrieved.data, certRetrieved.size);
+// KW certmgr_release_certificate_data(&descriptor);
+// KW break;
+// KW }
+// KW certmgr_release_certificate_data(&descriptor);
+// KW }
+// KW
+// KW if(ERR_NO_MORE_CERTIFICATES == result) {
+// KW LogError("Certificates not found");
+// KW return CERTIFICATE_NOT_FOUND;
+// KW }
+// KW if(result != OPERATION_SUCCESS){
+// KW LogError("Certificate Manager Error");
+// KW return UNKNOWN_ERROR;
+// KW }
+// KW return NO_ERROR;
+// KW }
+
+CertificateLoader::CertificateLoaderResult CertificateLoader::
+ loadCertificateWithECKEY(const std::string &curveName,
+ const std::string &publicKey)
+{
+ (void) curveName;
+ (void) publicKey;
+ LogError("Not implemented.");
+ return UNKNOWN_ERROR;
+ // if(curveName != OID_CURVE_SECP256R1){
+ // LogError("Found field id: " << curveName << " Expected: " << OID_CURVE_SECP256R1);
+ // return UNSUPPORTED_CERTIFICATE_FIELD;
+ // }
+ //
+ // CertificateLoaderECDSA comparator(publicKey);
+ //
+ // CertificateLoaderResult result = NO_ERROR;
+ // for(int i=0; storeId[i]; ++i){
+ // result = loadCertificate(std::string(storeId[i]), &comparator);
+ //
+ // if(result == ERR_NO_MORE_CERTIFICATES)
+ // continue;
+ //
+ // return result;
+ // }
+ //
+ // return result;
+}
+
+CertificateLoader::CertificateLoaderResult CertificateLoader::
+ loadCertificateFromRawData(const std::string &rawData)
+{
+ Try {
+ m_certificatePtr =
+ CertificatePtr(new Certificate(rawData, Certificate::FORM_BASE64));
+ } Catch(Certificate::Exception::Base) {
+ LogWarning("Error reading certificate by openssl.");
+ return UNKNOWN_ERROR;
+ }
+
+ // Check the key length if sig algorithm is RSA
+ EVP_PKEY *pKey = X509_get_pubkey(m_certificatePtr->getX509());
+
+ if (pKey->type == EVP_PKEY_RSA) {
+ RSA* pRSA = pKey->pkey.rsa;
+
+ if (pRSA) {
+ int keyLength = RSA_size(pRSA);
+
+ // key Length (modulus) is in bytes
+ keyLength <<= 3;
+ LogDebug("RSA key length: " << keyLength << " bits");
+
+ if (keyLength < MIN_RSA_KEY_LENGTH) {
+ LogError(
+ "RSA key too short!" << "Has only " << keyLength << " bits");
+ return CERTIFICATE_SECURITY_ERROR;
+ }
+ }
+ }
+
+ return NO_ERROR;
+}
+
+// DEPRACETED FUNCTION
+//CertificateLoader::CertificateLoaderResult CertificateLoader::loadCertificateFromRawData(const std::string &rawData)
+//{
+// certmgr_mem_buff cmBuff = {0,0,0};
+//
+// long int size;
+// cmBuff.data = certmgr_util_base64_decode(const_cast<void*>(static_cast<const void*>(rawData.c_str())), rawData.size(), &size);
+//
+// cmBuff.firstFree = cmBuff.size = size;
+//
+// certmgr_cert_descriptor descriptor;
+//
+// long int result = certmgr_extract_certificate_data(&cmBuff, &descriptor);
+//
+// if (result != OPERATION_SUCCESS)
+// {
+// LogError("Unable to load certificate");
+// return UNKNOWN_ERROR;
+// }
+//
+// certmgr_release_certificate_data(&descriptor);
+//
+// m_certificatePtr = CertificatePtr(new Certificate(cmBuff));
+//
+// // we have to use temp pointer cause d2i_x509 modifies its input
+// const unsigned char* tmpPtr = cmBuff.data;
+// X509* pCertificate = d2i_X509(NULL, &tmpPtr, cmBuff.size);
+//
+// if (pCertificate)
+// {
+// SSLSmartContainer<X509> pX509(pCertificate);
+//
+// // Check the key length if sig algorithm is RSA
+// EVP_PKEY *pKey = X509_get_pubkey(pX509);
+//
+// if (pKey->type == EVP_PKEY_RSA)
+// {
+// RSA* pRSA = pKey->pkey.rsa;
+//
+// if (pRSA)
+// {
+// int keyLength = RSA_size(pRSA);
+//
+// // key Length (modulus) is in bytes
+// keyLength <<= 3;
+// LogDebug("RSA key length: " << keyLength << " bits");
+//
+// if (keyLength < MIN_RSA_KEY_LENGTH)
+// {
+// LogError("RSA key too short!" << "Has only " << keyLength << " bits");
+// return CERTIFICATE_SECURITY_ERROR;
+// }
+// }
+// }
+// }
+//
+// return NO_ERROR;
+//}
+
+CertificateLoader::CertificateLoaderResult CertificateLoader::
+ loadCertificateBasedOnDSAComponents(const std::string& strP,
+ const std::string& strQ,
+ const std::string& strG,
+ const std::string& strY,
+ const std::string& strJ,
+ const std::string& strSeed,
+ const std::string& strPGenCounter)
+{
+ (void) strP;
+ (void) strQ;
+ (void) strG;
+ (void) strY;
+ (void) strJ;
+ (void) strSeed;
+ (void) strPGenCounter;
+ LogError("Not implemented.");
+ return UNKNOWN_ERROR;
+ // (void)strY;
+ // (void)strJ;
+ // (void)strSeed;
+ // (void)strPGenCounter;
+ //
+ // long int result = UNKNOWN_ERROR;
+ //
+ // char storeId[CERTMGR_MAX_PLUGIN_ID_SIZE];
+ // char type[CERTMGR_MAX_CERT_TYPE_SIZE];
+ // certmgr_cert_id certId;
+ // certmgr_ctx context;
+ // certmgr_mem_buff certRetrieved;
+ //
+ // unsigned char buffer[CERTMGR_MAX_BUFFER_SIZE];
+ //
+ // certmgr_cert_descriptor descriptor;
+ //
+ // certRetrieved.data = buffer;
+ // certRetrieved.firstFree = 0;
+ // certRetrieved.size = CERTMGR_MAX_BUFFER_SIZE;
+ // certId.storeId = storeId;
+ // certId.type = type;
+ //
+ // CERTMGR_INIT_CONTEXT((&context), (sizeof(context)))
+ // std::string strStoreType("Operator");
+ // strncpy(context.storeId, strStoreType.c_str(), strStoreType.length());
+ //
+ // for (certRetrieved.firstFree = 0;
+ // OPERATION_SUCCESS == (result = certmgr_retrieve_certificate_from_store(&context, &certRetrieved, &certId));
+ // certRetrieved.firstFree = 0)
+ // {
+ //
+ // if (OPERATION_SUCCESS != certmgr_extract_certificate_data(&certRetrieved, &descriptor))
+ // {
+ // LogDebug("unable to retrieve cert from storage");
+ // continue;
+ // }
+ //
+ // X509* pCertificate = d2i_X509(NULL, (const unsigned char**) &(certRetrieved.data), certRetrieved.size);
+ //
+ // if (pCertificate)
+ // {
+ // EVP_PKEY *pKey = X509_get_pubkey(pCertificate);
+ //
+ // if (pKey->type == EVP_PKEY_DSA)
+ // {
+ // DSA* pDSA = pKey->pkey.dsa;
+ //
+ // if (pDSA)
+ // {
+ // BIGNUM *pDSApBigNum = NULL, *pDSAqBigNum = NULL, *pDSAgBigNum = NULL;
+ //
+ // convertBase64NodeToBigNum(strP, &pDSApBigNum);
+ // convertBase64NodeToBigNum(strQ, &pDSAqBigNum);
+ // convertBase64NodeToBigNum(strG, &pDSAgBigNum);
+ //
+ // if (pDSApBigNum && pDSAqBigNum && pDSAgBigNum &&
+ // BN_cmp(pDSApBigNum, pDSA->p) == 0 &&
+ // BN_cmp(pDSAqBigNum, pDSA->q) == 0 &&
+ // BN_cmp(pDSAgBigNum, pDSA->g) == 0)
+ // {
+ // LogInfo("DSA Certificate found");
+ // /* TODO load this certificate to m_cmBuff value */
+ // LogError("Not implemented!");
+ //
+ // EVP_PKEY_free(pKey);
+ // X509_free(pCertificate);
+ //
+ // BN_free(pDSApBigNum);
+ // BN_free(pDSAqBigNum);
+ // BN_free(pDSAgBigNum);
+ //
+ // certmgr_release_certificate_data(&descriptor);
+ // return NO_ERROR;
+ // }
+ //
+ // if (pDSApBigNum)
+ // {
+ // BN_free(pDSApBigNum);
+ // }
+ // if (pDSAqBigNum)
+ // {
+ // BN_free(pDSAqBigNum);
+ // }
+ // if (pDSAgBigNum)
+ // {
+ // BN_free(pDSAgBigNum);
+ // }
+ //
+ // }
+ // EVP_PKEY_free(pKey);
+ // }
+ // X509_free(pCertificate);
+ // }
+ // else
+ // LogError("Unable to load certificate");
+ //
+ // certmgr_release_certificate_data(&descriptor);
+ // }
+ //
+ // LogError("No DSA certificate with given parameters");
+ //
+ // return CERTIFICATE_NOT_FOUND;
+}
+
+bool CertificateLoader::convertBase64NodeToBigNum(const std::string& strNode,
+ BIGNUM** ppBigNum)
+{
+ (void) strNode;
+ (void) ppBigNum;
+ LogError("Not implemented.");
+ return false;
+ // if (!ppBigNum || *ppBigNum != NULL)
+ // {
+ // LogError("Ptr variable not initialized properly!");
+ // return false;
+ // }
+ //
+ // // decode base64 to binary
+ // long int binBuffLength = 0;
+ // unsigned char* binBuff = NULL;
+ //
+ // binBuff = certmgr_util_base64_decode(const_cast<char*> (strNode.c_str()), strNode.length(), &binBuffLength);
+ //
+ // if (!binBuff)
+ // {
+ // LogError("base64 decode failed");
+ // return false;
+ // }
+ //
+ // // convert binary to bignum
+ // *ppBigNum = BN_bin2bn(binBuff, binBuffLength, *ppBigNum);
+ //
+ // free(binBuff);
+ //
+ // if (!(*ppBigNum))
+ // {
+ // LogError("Conversion from node to bignum failed");
+ // return false;
+ // }
+ //
+ // return true;
+}
+
+// KW bool CertificateLoader::convertBigNumToBase64Node(const BIGNUM* pBigNum, std::string& strNode)
+// KW {
+// KW if (!pBigNum)
+// KW {
+// KW LogError("null ptr");
+// KW return false;
+// KW }
+// KW
+// KW int nNumLength = BN_num_bytes(pBigNum);
+// KW unsigned char* buffer = new unsigned char[nNumLength + 1];
+// KW
+// KW // convert bignum to binary format
+// KW if (BN_bn2bin(pBigNum, buffer) < 0)
+// KW {
+// KW LogError("Conversion from bignum to binary failed");
+// KW delete []buffer;
+// KW return false;
+// KW }
+// KW
+// KW char* pBase64Node = NULL;
+// KW unsigned long int buffLen = 0;
+// KW certmgr_util_base64_encode(buffer, (unsigned long int) nNumLength, &pBase64Node, &buffLen);
+// KW
+// KW strNode.assign(pBase64Node, buffLen);
+// KW
+// KW delete []buffer;
+// KW return true;
+// KW }
+} // namespace ValidationCore
+
--- /dev/null
+/*
+ * 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.
+ */
+#ifndef _CERTIFICATELOADER_H_
+#define _CERTIFICATELOADER_H_
+
+#include <string>
+#include <string.h>
+
+#include <dpl/noncopyable.h>
+#include <openssl/ssl.h>
+
+#include <cert-service.h>
+
+#include <vcore/Certificate.h>
+
+namespace ValidationCore {
+class CertificateLoader : public DPL::Noncopyable
+{
+ public:
+ class CertificateLoaderComparator
+ {
+ public:
+ virtual bool compare(X509 *x509cert) = 0;
+ virtual ~CertificateLoaderComparator()
+ {
+ }
+ };
+
+ enum CertificateLoaderResult
+ {
+ NO_ERROR,
+ CERTIFICATE_NOT_FOUND,
+ UNSUPPORTED_CERTIFICATE_FIELD,
+ WRONG_ARGUMENTS,
+ CERTIFICATE_SECURITY_ERROR, //!< there are some issues with certificate security (i.e. key too short)
+ UNKNOWN_ERROR
+ };
+
+ CertificateLoader()
+ {
+ }
+
+ virtual ~CertificateLoader()
+ {
+ }
+
+ CertificateLoaderResult loadCertificate(const std::string& storage,
+ CertificateLoaderComparator *cmp);
+
+ CertificateLoaderResult loadCertificateBasedOnSubjectName(
+ const std::string &subjectName);
+ CertificateLoaderResult loadCertificateBasedOnExponentAndModulus(
+ const std::string &m_modulus,
+ const std::string &m_exponent);
+ // KW CertificateLoaderResult loadCertificateBasedOnIssuerName(const std::string &isserName,
+ // KW const std::string &serialNumber);
+
+ CertificateLoaderResult loadCertificateFromRawData(
+ const std::string &rawData);
+
+ CertificateLoaderResult loadCertificateBasedOnDSAComponents(
+ const std::string& strP,
+ const std::string& strQ,
+ const std::string& strG,
+ const std::string& strY,
+ const std::string& strJ,
+ const std::string& strSeed,
+ const std::string& strPGenCounter);
+
+ CertificateLoaderResult loadCertificateWithECKEY(
+ const std::string &curveName,
+ const std::string &publicKey);
+
+ /**
+ * converts base64 encoded node to SSL bignum
+ * allocates mem on *ppBigNum, don't forget to free it later with BN_free!
+ * returns conversion status
+ */
+ static bool convertBase64NodeToBigNum(const std::string& strNode,
+ BIGNUM** ppBigNum);
+
+ /*
+ * encodes SSL bignum into base64 octstring
+ * returns conversion status
+ */
+ // KW static bool convertBigNumToBase64Node(const BIGNUM* pBigNum, std::string& strNode);
+
+ CertificatePtr getCertificatePtr() const
+ {
+ return m_certificatePtr;
+ }
+ private:
+ CertificatePtr m_certificatePtr;
+};
+} // namespace ValidationCore
+
+#endif // _CERTIFICATELOADER_H_
--- /dev/null
+/*
+ * 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.
+ */
+#ifndef VCORE_SRC_VCORE_CERTIFICATESTORAGE_H
+#define VCORE_SRC_VCORE_CERTIFICATESTORAGE_H
+
+#include <list>
+#include <openssl/x509.h>
+
+namespace ValidationCore {
+typedef std::list < X509* > X509CertificatesList;
+}
+
+#endif // VCORE_SRC_VCORE_CERTIFICATESTORAGE_H
--- /dev/null
+/*
+ * 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.
+ */
+/*!
+ * @author Bartlomiej Grzelewski (b.grzelewski@gmail.com)
+ * @version 0.1
+ * @file CertificateVerifier.cpp
+ * @brief This class integrates OCSP and CRL.
+ */
+#include <vcore/CertificateVerifier.h>
+
+#include <dpl/assert.h>
+#include <dpl/foreach.h>
+#include <dpl/log/log.h>
+
+namespace ValidationCore {
+
+CertificateVerifier::CertificateVerifier(bool enableOcsp, bool enableCrl)
+: m_enableOcsp(enableOcsp)
+, m_enableCrl(enableCrl)
+{}
+
+VerificationStatus CertificateVerifier::check(
+ CertificateCollection &certCollection) const
+{
+ LogDebug("== Certificate collection validation start ==");
+ Assert(certCollection.isChain() && "Collection must form chain.");
+
+ VerificationStatus statusOcsp;
+ VerificationStatus statusCrl;
+
+ if (m_enableOcsp) {
+ statusOcsp = obtainOcspStatus(certCollection);
+ } else {
+ statusOcsp = VERIFICATION_STATUS_GOOD;
+ }
+
+ if (m_enableCrl) {
+ statusCrl = obtainCrlStatus(certCollection);
+ } else {
+ statusCrl = VERIFICATION_STATUS_GOOD;
+ }
+ LogDebug("== Certificate collection validation end ==");
+ return getStatus(statusOcsp, statusCrl);
+}
+
+VerificationStatus CertificateVerifier::obtainOcspStatus(
+ const CertificateCollection &chain) const
+{
+ LogDebug("== Obtain ocsp status ==");
+ CachedOCSP ocsp;
+ return ocsp.check(chain);
+}
+
+VerificationStatus CertificateVerifier::obtainCrlStatus(
+ const CertificateCollection &chain) const
+{
+ LogDebug("== Obtain crl status ==");
+ CachedCRL crl;
+ return crl.check(chain);
+}
+
+VerificationStatus CertificateVerifier::getStatus(
+ VerificationStatus ocsp,
+ VerificationStatus crl) const
+{
+ if (ocsp == VERIFICATION_STATUS_REVOKED ||
+ crl == VERIFICATION_STATUS_REVOKED)
+ {
+ LogDebug("Return status: REVOKED");
+ return VERIFICATION_STATUS_REVOKED;
+ }
+
+ if (ocsp == VERIFICATION_STATUS_GOOD) {
+ LogDebug("Return status: GOOD");
+ return VERIFICATION_STATUS_GOOD;
+ }
+
+ if (ocsp == VERIFICATION_STATUS_UNKNOWN) {
+ LogDebug("Return status: UNKNOWN");
+ return VERIFICATION_STATUS_UNKNOWN;
+ }
+
+ if (ocsp == VERIFICATION_STATUS_NOT_SUPPORT) {
+ LogDebug("Return status: NOT_SUPPORT");
+ return VERIFICATION_STATUS_GOOD;
+ }
+
+ LogDebug("Return status: ERROR");
+ return VERIFICATION_STATUS_ERROR;
+}
+
+VerificationStatus CertificateVerifier::checkEndEntity(
+ CertificateCollectionList &collectionList) const
+{
+ VerificationStatusSet statusOcsp;
+ VerificationStatusSet statusCrl;
+
+ if (m_enableOcsp) {
+ CachedOCSP ocsp;
+ FOREACH(it, collectionList){
+ statusOcsp.add(ocsp.checkEndEntity(*it));
+ }
+ } else {
+ statusOcsp.add(VERIFICATION_STATUS_GOOD);
+ }
+
+ if (m_enableCrl) {
+ CachedCRL crl;
+ FOREACH(it, collectionList){
+ statusCrl.add(crl.checkEndEntity(*it));
+ }
+ } else {
+ statusCrl.add(VERIFICATION_STATUS_GOOD);
+ }
+ LogDebug("== Certificate collection validateion end ==");
+ return getStatus(statusOcsp.convertToStatus(), statusCrl.convertToStatus());
+}
+
+} // namespace ValidationCore
--- /dev/null
+/*
+ * 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.
+ */
+/*!
+ * @author Bartlomiej Grzelewski (b.grzelewski@gmail.com)
+ * @version 0.1
+ * @file CertificateVerifier.h
+ * @brief This class integrates OCSP and CRL into one module.
+ */
+#ifndef _VALIDATION_CORE_CERTIFICATE_VERIFIER_H_
+#define _VALIDATION_CORE_CERTIFICATE_VERIFIER_H_
+
+#include <vcore/Certificate.h>
+#include <vcore/CertificateCollection.h>
+#include <vcore/CachedCRL.h>
+#include <vcore/CachedOCSP.h>
+#include <vcore/VerificationStatus.h>
+
+namespace ValidationCore {
+
+class CertificateVerifier {
+ public:
+ explicit CertificateVerifier(bool enableOcsp, bool enableCrl);
+ ~CertificateVerifier(){}
+
+ /*
+ * Run OCSP and CRL for all certificates in collection.
+ * Collection must represent chain.
+ *
+ * Evaluate status. This function converts ocsp status set
+ * into one status - the most restricted. This one ocsp status
+ * and status from crl is evaluated to end result.
+ *
+ * Algorithm to evaluate result is represented in table:
+ *
+ * +--------------+-------+-------+-------+------------+---------+
+ * | OCSP |Good |Revoked|Unknown|Undetermined|Not |
+ * | | | | | |supported|
+ * | CRL | | | | | |
+ * +--------------+-------+-------+-------+------------+---------+
+ * | GOOD |GOOD |Revoked|Unknown|Undetermined|Good |
+ * +--------------+-------+-------+-------+------------+---------+
+ * | REVOKED |Revoked|Revoked|Revoked|Revoked |Revoked |
+ * +--------------+-------+-------+-------+------------+---------+
+ * | UNDETERMINED |Good |Revoked|Unknown|Undetermined|Good |
+ * +--------------+-------+-------+-------+------------+---------+
+ * | Not supported|Good |Revoked|Unknown|Undetermined|Good |
+ * +--------------+-------+-------+-------+------------+---------+
+ *
+ * As Undetermind function returns VERIFICATION_STATUS_ERROR.
+ */
+
+ VerificationStatus check(CertificateCollection &certCollection) const;
+
+ VerificationStatus checkEndEntity(
+ CertificateCollectionList &certCollectionList) const;
+
+ private:
+ VerificationStatus obtainOcspStatus(
+ const CertificateCollection &chain) const;
+ VerificationStatus obtainCrlStatus(
+ const CertificateCollection &chain) const;
+ VerificationStatus getStatus(VerificationStatus ocsp,
+ VerificationStatus crl) const;
+
+ bool m_enableOcsp;
+ bool m_enableCrl;
+};
+
+} // namespace ValidationCore
+
+#endif // _VALIDATION_CORE_CERTIFICATE_VERIFIER_H_
+
--- /dev/null
+/*
+ * 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.
+ */
+
+#include <vcore/Config.h>
+
+#include <dpl/singleton_impl.h>
+IMPLEMENT_SINGLETON(ValidationCore::Config)
--- /dev/null
+/*
+ * 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.
+ */
+
+#ifndef _SRC_VALIDATION_CORE_VALIDATION_CORE_CONFIG_H_
+#define _SRC_VALIDATION_CORE_VALIDATION_CORE_CONFIG_H_
+
+#include <string>
+
+#include <dpl/singleton.h>
+
+namespace ValidationCore {
+class Config {
+public:
+ /*
+ * Set path to config file with certificate description.
+ */
+ bool setXMLConfigPath(const std::string& path) {
+ if (!m_certificateXMLConfigPath.empty()) {
+ return false;
+ }
+ m_certificateXMLConfigPath = path;
+ return true;
+ }
+
+ /*
+ * Set path to schema of config file.
+ */
+ bool setXMLSchemaPath(const std::string& path) {
+ if (!m_certificateXMLSchemaPath.empty()) {
+ return false;
+ }
+ m_certificateXMLSchemaPath = path;
+ return true;
+ }
+
+ /*
+ * Get path to config file with certificate description.
+ */
+ std::string getXMLConfigPath() {
+ return m_certificateXMLConfigPath;
+ }
+
+ /*
+ * Get path to schema of config file.
+ */
+ std::string getXMLSchemaPath() {
+ return m_certificateXMLSchemaPath;
+ }
+
+private:
+ std::string m_certificateXMLConfigPath;
+ std::string m_certificateXMLSchemaPath;
+};
+
+typedef DPL::Singleton<Config> ConfigSingleton;
+
+} // namespace ValidationCore
+
+#endif // _SRC_VALIDATION_CORE_VALIDATION_CORE_CONFIG_H_
+
--- /dev/null
+/*
+ * 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 wrt_crypto_hash.cpp
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of cryptographic hasing algorithms
+ */
+#include <vcore/CryptoHash.h>
+
+#include <openssl/bio.h>
+#include <openssl/ssl.h>
+#include <openssl/evp.h>
+#include <stdexcept>
+
+#include <vcore/Base64.h>
+
+namespace ValidationCore
+{
+namespace Crypto
+{
+namespace Hash
+{
+namespace // anonymous
+{
+const size_t HASH_DIGEST_STREAM_FEED_SIZE = 1024;
+
+std::string Raw2Base64(const void *buffer, size_t bufferSize)
+{
+ BIO *bio64, *biomem;
+
+ if ((bio64 = BIO_new(BIO_f_base64())) == NULL)
+ ThrowMsg(AppendFailed, "BIO_new(BIO_f_base64()) failed!");
+
+ if ((biomem = BIO_new(BIO_s_mem())) == NULL)
+ {
+ BIO_free_all(bio64);
+ ThrowMsg(AppendFailed, "BIO_new(BIO_s_mem()) failed!");
+ }
+
+ bio64 = BIO_push(bio64, biomem);
+
+ if (BIO_write(bio64, buffer, static_cast<int>(bufferSize)) <= 0)
+ {
+ BIO_free_all(bio64);
+ ThrowMsg(AppendFailed, "BIO_write failed!");
+ }
+
+ if (BIO_flush(bio64) <= 0)
+ {
+ BIO_free_all(bio64);
+ ThrowMsg(AppendFailed, "BIO_flush failed!");
+ }
+
+ BUF_MEM *bioptr;
+ BIO_get_mem_ptr(bio64, &bioptr);
+
+ std::string base64 = std::string(static_cast<const char *>(bioptr->data), static_cast<const char *>(bioptr->data + bioptr->length));
+
+ BIO_free_all(bio64);
+ return base64;
+}
+} // namespace anonymous
+
+Base::Base()
+ : m_hasFinal(false)
+{
+}
+
+Base::~Base()
+{
+}
+
+void Base::Append(const char *buffer)
+{
+ if (m_hasFinal)
+ ThrowMsg(OutOfSequence, "Cannot append hash after final update!");
+
+ HashUpdate(buffer, strlen(buffer));
+}
+
+void Base::Append(const char *buffer, size_t bufferSize)
+{
+ if (m_hasFinal)
+ ThrowMsg(OutOfSequence, "Cannot append hash after final update!");
+
+ HashUpdate(buffer, bufferSize);
+}
+
+void Base::Append(const std::string &buffer)
+{
+ if (m_hasFinal)
+ ThrowMsg(OutOfSequence, "Cannot append hash after final update!");
+
+ HashUpdate(buffer.c_str(), buffer.size());
+}
+
+void Base::Append(std::istream &stream)
+{
+ if (m_hasFinal)
+ ThrowMsg(OutOfSequence, "Cannot append hash after final update!");
+
+ char buffer[HASH_DIGEST_STREAM_FEED_SIZE];
+
+ do
+ {
+ stream.read(buffer, HASH_DIGEST_STREAM_FEED_SIZE);
+
+ if (stream.gcount() > 0)
+ Append(static_cast<void *>(buffer), static_cast<size_t>(stream.gcount()));
+
+ } while (stream.gcount() > 0);
+}
+
+void Base::Append(const void *data, size_t dataSize)
+{
+ if (m_hasFinal)
+ ThrowMsg(OutOfSequence, "Cannot append hash after final update!");
+
+ HashUpdate(data, dataSize);
+}
+
+void Base::Finish()
+{
+ if (m_hasFinal)
+ return;
+
+ // Finalize hashing algorithm
+ m_raw = HashFinal();
+
+ // Convert to base 64 string
+ Base64Encoder encoder;
+ encoder.reset();
+ encoder.append(std::string(m_raw.begin(), m_raw.end()));
+ encoder.finalize();
+ m_base64StringHash = encoder.get();
+
+ m_hasFinal = true;
+}
+
+std::string Base::ToBase64String() const
+{
+ return m_base64StringHash;
+}
+
+Raw Base::GetHash() const
+{
+ return m_raw;
+}
+
+OpenSSL::OpenSSL(const EVP_MD *evpMd)
+ : m_finalized(false)
+{
+ EVP_MD_CTX_init(&m_context);
+
+ if (EVP_DigestInit(&m_context, evpMd) != 1)
+ ThrowMsg(AppendFailed, "EVP_DigestInit failed!");
+}
+
+OpenSSL::~OpenSSL()
+{
+ if (!m_finalized)
+ {
+ // Just clean context
+ EVP_MD_CTX_cleanup(&m_context);
+ m_finalized = true;
+ }
+}
+
+void OpenSSL::HashUpdate(const void *data, size_t dataSize)
+{
+ if (m_finalized)
+ ThrowMsg(AppendFailed, "OpenSSLHash hash already finalized!");
+
+ if (EVP_DigestUpdate(&m_context, data, dataSize) != 1)
+ ThrowMsg(AppendFailed, "EVP_DigestUpdate failed!");
+}
+
+Hash::Raw OpenSSL::HashFinal()
+{
+ if (m_finalized)
+ ThrowMsg(AppendFailed, "OpenSSLHash hash already finalized!");
+
+ unsigned char hash[EVP_MAX_MD_SIZE] = {};
+ unsigned int hashLength;
+
+ // Also cleans context
+ if (EVP_DigestFinal(&m_context, hash, &hashLength) != 1)
+ ThrowMsg(AppendFailed, "EVP_DigestFinal failed!");
+
+ m_finalized = true;
+ return Raw(hash, hash + hashLength);
+}
+
+} // namespace Hash
+} // namespace Crypto
+} // namespace ValidationCore
--- /dev/null
+/*
+ * 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 crypto_hash.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of cryptographic hasing algorithms
+ */
+#ifndef _CRYPTO_HASH_H_
+#define _CRYPTO_HASH_H_
+
+#include <dpl/exception.h>
+#include <openssl/evp.h>
+#include <istream>
+#include <string>
+#include <vector>
+
+namespace ValidationCore
+{
+namespace Crypto
+{
+namespace Hash
+{
+/**
+ * Raw hash buffer
+ */
+typedef std::vector<unsigned char> Raw;
+
+/**
+ * Append called out of sequence
+ */
+DECLARE_EXCEPTION_TYPE(DPL::Exception, OutOfSequence)
+
+/**
+ * Append failed internally
+ */
+DECLARE_EXCEPTION_TYPE(DPL::Exception, AppendFailed)
+
+class Base
+{
+private:
+ Raw m_raw;
+ std::string m_base64StringHash;
+ bool m_hasFinal;
+
+protected:
+ virtual void HashUpdate(const void *data, size_t dataSize) = 0;
+ virtual Raw HashFinal() = 0;
+
+public:
+ Base();
+ virtual ~Base();
+
+ virtual void Append(const char *buffer);
+ virtual void Append(const char *buffer, size_t bufferSize);
+ virtual void Append(const std::string &buffer);
+ virtual void Append(std::istream &stream);
+ virtual void Append(const void *data, size_t dataSize);
+
+ virtual void Finish();
+
+ virtual std::string ToBase64String() const;
+ virtual Raw GetHash() const;
+};
+
+/**
+ * OpenSSL hashing algorithm base
+ */
+class OpenSSL
+ : public Base
+{
+private:
+ EVP_MD_CTX m_context;
+ bool m_finalized;
+
+protected:
+ virtual void HashUpdate(const void *data, size_t dataSize);
+ virtual Raw HashFinal();
+
+public:
+ OpenSSL(const EVP_MD *evpMd);
+ virtual ~OpenSSL();
+};
+
+#define DECLARE_OPENSSL_HASH_ALGORITHM(ClassName, EvpMd) \
+ class ClassName \
+ : public OpenSSL \
+ { \
+ public: \
+ ClassName() : OpenSSL(EvpMd()) {} \
+ virtual ~ClassName() {} \
+ };
+
+DECLARE_OPENSSL_HASH_ALGORITHM(MD2, EVP_md2)
+DECLARE_OPENSSL_HASH_ALGORITHM(MD4, EVP_md4)
+DECLARE_OPENSSL_HASH_ALGORITHM(MD5, EVP_md5)
+DECLARE_OPENSSL_HASH_ALGORITHM(SHA, EVP_sha)
+DECLARE_OPENSSL_HASH_ALGORITHM(SHA1, EVP_sha1)
+DECLARE_OPENSSL_HASH_ALGORITHM(DSS, EVP_dss)
+DECLARE_OPENSSL_HASH_ALGORITHM(DSS1, EVP_dss1)
+DECLARE_OPENSSL_HASH_ALGORITHM(ECDSA, EVP_ecdsa)
+DECLARE_OPENSSL_HASH_ALGORITHM(SHA224, EVP_sha224)
+DECLARE_OPENSSL_HASH_ALGORITHM(SHA256, EVP_sha256)
+DECLARE_OPENSSL_HASH_ALGORITHM(SHA384, EVP_sha384)
+DECLARE_OPENSSL_HASH_ALGORITHM(SHA512, EVP_sha512)
+
+#undef DECLARE_OPENSSL_HASH_ALGORITHM
+
+} // namespace Hash
+} // namespace Crypto
+} // namespace ValidationCore
+
+#endif // DPL_CRYPTO_HASH_H
--- /dev/null
+/*
+ * 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 webruntime_database.cpp
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file contains the definition of webruntime database
+ */
+#include <vcore/Database.h>
+
+DPL::Mutex g_vcoreDbQueriesMutex;
--- /dev/null
+/*
+ * 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 webruntime_database.h
+ * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
+ * @version 1.0
+ * @brief This file contains the declaration of webruntime database
+ */
+#ifndef VCORE_SRC_VCORE_DATABASE_H
+#define VCORE_SRC_VCORE_DATABASE_H
+
+#include <dpl/db/thread_database_support.h>
+#include <dpl/db/sql_connection.h>
+#include <dpl/mutex.h>
+#include <dpl/thread.h>
+
+extern DPL::Mutex g_vcoreDbQueriesMutex;
+
+#define VCORE_DB_INTERNAL(tlsCommand, InternalType, interface) \
+ static DPL::ThreadLocalVariable<InternalType> *tlsCommand ## Ptr = NULL; \
+ { \
+ DPL::Mutex::ScopedLock lock(&g_vcoreDbQueriesMutex); \
+ if (!tlsCommand ## Ptr) { \
+ static DPL::ThreadLocalVariable<InternalType> tmp; \
+ tlsCommand ## Ptr = &tmp; \
+ } \
+ } \
+ DPL::ThreadLocalVariable<InternalType> &tlsCommand = *tlsCommand ## Ptr; \
+ if (tlsCommand.IsNull()) { tlsCommand = InternalType(interface); }
+
+#define VCORE_DB_SELECT(name, type, interface) \
+ VCORE_DB_INTERNAL(name, type::Select, interface)
+
+#define VCORE_DB_INSERT(name, type, interface) \
+ VCORE_DB_INTERNAL(name, type::Insert, interface)
+
+#define VCORE_DB_UPDATE(name, type, interface) \
+ VCORE_DB_INTERNAL(name, type::Update, interface)
+
+#define VCORE_DB_DELETE(name, type, interface) \
+ VCORE_DB_INTERNAL(name, type::Delete, interface)
+
+#endif // define VCORE_SRC_VCORE_DATABASE_H
--- /dev/null
+/*
+ * 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 DeveloperModeValidator.cpp
+ * @author Bartosz Janiak (b.janiak@samsung.com)
+ * @version 1.0
+ * @brief DeveloperModeValidatorValidator - implementing WAC 2.0 spec, including TargetRestriction
+ */
+
+#include <vcore/DeveloperModeValidator.h>
+
+#include <algorithm>
+#include <vconf.h>
+#include <dpl/log/log.h>
+#include <dpl/scoped_free.h>
+
+namespace ValidationCore {
+
+DeveloperModeValidator::DeveloperModeValidator(bool complianceMode,
+ const std::string& fakeIMEI,
+ const std::string& fakeMEID) :
+ m_complianceModeEnabled(complianceMode),
+ m_developerModeEnabled(true),
+ m_fakeIMEI(fakeIMEI),
+ m_fakeMEID(fakeMEID)
+{
+}
+
+DeveloperModeValidator::DeveloperModeValidator(bool complianceMode,
+ bool developerMode,
+ const std::string& fakeIMEI,
+ const std::string& fakeMEID,
+ const std::string& realMEID) :
+ m_complianceModeEnabled(complianceMode),
+ m_developerModeEnabled(developerMode),
+ m_fakeIMEI(fakeIMEI),
+ m_fakeMEID(fakeMEID),
+ m_realMEID(realMEID)
+{
+}
+
+void DeveloperModeValidator::check(const SignatureData &data)
+{
+ LogDebug("entered");
+ const SignatureData::IMEIList& IMEIList = data.getIMEIList();
+ const SignatureData::MEIDList& MEIDList = data.getMEIDList();
+
+ if (IMEIList.empty() && MEIDList.empty()) {
+ LogDebug("No TargetRestriction in signature.");
+ return;
+ }
+
+ if (!m_developerModeEnabled) {
+ Throw(Exception::NoTargetRestrictionSatisfied);
+ }
+
+ if (!IMEIList.empty()) {
+ std::string phoneIMEIString = m_fakeIMEI;
+ if (!m_complianceModeEnabled) {
+ LogDebug("Compilance Mode is not enabled");
+ DPL::ScopedFree<char> phoneIMEI(
+ vconf_get_str(VCONFKEY_TELEPHONY_IMEI));
+ if (!phoneIMEI.Get()) {
+ ThrowMsg(Exception::NoTargetRestrictionSatisfied,
+ "Unable to get phone IMEI from vconf.");
+ }
+ phoneIMEIString = phoneIMEI.Get();
+ }
+
+ LogDebug("Phone IMEI: " << phoneIMEIString);
+ if (IMEIList.end() ==
+ std::find(IMEIList.begin(), IMEIList.end(), phoneIMEIString))
+ {
+ Throw(Exception::NoTargetRestrictionSatisfied);
+ }
+ }
+
+ if (!MEIDList.empty()) {
+ std::string phoneMEIDString = m_fakeMEID;
+ if (!m_complianceModeEnabled)
+ {
+ if (m_realMEID.empty())
+ {
+ ThrowMsg(Exception::NoTargetRestrictionSatisfied,
+ "Unable to get phone MEID from Tapi service.");
+ }
+ phoneMEIDString = m_realMEID;
+ }
+
+ LogDebug("Phone MEID: " << phoneMEIDString);
+ if (MEIDList.end() ==
+ std::find(MEIDList.begin(), MEIDList.end(), phoneMEIDString))
+ {
+ Throw(Exception::NoTargetRestrictionSatisfied);
+ }
+ }
+ LogDebug("exit: ok");
+}
+
+} //ValidationCore
--- /dev/null
+/*
+ * 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 DeveloperModeValidator.h
+ * @author Bartosz Janiak (b.janiak@samsung.com)
+ * @version 1.0
+ * @brief DeveloperModeValidatorValidator - implementing WAC 2.0 spec, including TargetRestriction
+ */
+#ifndef _VALIDATION_CORE_DEVELOPER_MODE_VALIDATOR_H_
+#define _VALIDATION_CORE_DEVELOPER_MODE_VALIDATOR_H_
+
+#include <string>
+#include <dpl/exception.h>
+#include <vcore/SignatureData.h>
+
+namespace ValidationCore {
+
+class DeveloperModeValidator
+{
+ public:
+ explicit DeveloperModeValidator(
+ bool complianceMode = false,
+ const std::string &fakeIMEI = "",
+ const std::string &fakeMEID = "") __attribute__((deprecated));
+
+ explicit DeveloperModeValidator(bool complianceMode = false,
+ bool developerMode = false,
+ const std::string &fakeIMEI = "",
+ const std::string &fakeMEID = "",
+ const std::string &realMEID = "");
+
+ class Exception
+ {
+ public:
+ DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
+ DECLARE_EXCEPTION_TYPE(Base, UnableToLoadTestCertificate)
+ DECLARE_EXCEPTION_TYPE(Base, NoTargetRestrictionSatisfied)
+ };
+
+ void check(const SignatureData &data);
+ private:
+ bool m_complianceModeEnabled;
+ bool m_developerModeEnabled;
+ std::string m_fakeIMEI;
+ std::string m_fakeMEID;
+ std::string m_realMEID;
+};
+
+}
+#endif /* _VALIDATION_CORE_DEVELOPER_MODE_VALIDATOR_H_ */
+
--- /dev/null
+/*
+ * 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 AbstractResponseCache.h
+ * @author Tomasz Swierczek (t.swierczek@samsung.com)
+ * @version 0.1
+ * @brief Common interface for OCSP/CRL caches
+ */
+
+#ifndef _VALIDATION_CORE_IABSTRACT_RESPONSE_CACHE_H_
+#define _VALIDATION_CORE_IABSTRACT_RESPONSE_CACHE_H_
+
+#include <vcore/VerificationStatus.h>
+
+namespace ValidationCore {
+
+class CertificateCollection;
+
+class IAbstractResponseCache {
+ public:
+ virtual VerificationStatus check(const CertificateCollection &certs) = 0;
+ virtual VerificationStatus checkEndEntity(CertificateCollection &certs) = 0;
+ virtual void updateCache() = 0;
+
+ virtual ~IAbstractResponseCache()
+ {
+ }
+};
+
+} // namespace ValidationCore
+
+#endif /* _VALIDATION_CORE_IABSTRACT_RESPONSE_CACHE_H_ */
--- /dev/null
+/*
+ * 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.
+ */
+/*!
+ * @author Bartlomiej Grzelewski(b.grzelewski@samsung.com)
+ * @version 0.5
+ * @file OCPS.cpp
+ * @brief This class is used for hide OCSP implementation.
+ */
+
+#include <vcore/OCSPImpl.h>
+
+namespace ValidationCore {
+
+OCSP::OCSP() :
+ m_impl(new OCSPImpl())
+{}
+
+OCSP::~OCSP(){
+ delete m_impl;
+}
+
+ValidationCore::VerificationStatusSet OCSP::validateCertificateList(
+ const CertificateList &certs)
+{
+ return m_impl->validateCertificateList(certs);
+}
+
+VerificationStatus OCSP::checkEndEntity(
+ const CertificateCollection &chain)
+{
+ return m_impl->checkEndEntity(chain);
+}
+
+VerificationStatus OCSP::validateCertificate(CertificatePtr argCert,
+ CertificatePtr argIssuer)
+{
+ return m_impl->validateCertificate(argCert, argIssuer);
+}
+
+void OCSP::setDigestAlgorithmForCertId(DigestAlgorithm alg) {
+ return m_impl->setDigestAlgorithmForCertId(alg);
+}
+
+void OCSP::setDigestAlgorithmForRequest(DigestAlgorithm alg) {
+ return m_impl->setDigestAlgorithmForRequest(alg);
+}
+
+void OCSP::setTrustedStore(const CertificateList& certs) {
+ m_impl->setTrustedStore(certs);
+}
+
+void OCSP::setDefaultResponder(const char *uri) {
+ m_impl->setDefaultResponder(uri);
+}
+
+void OCSP::setUseDefaultResponder(bool value) {
+ m_impl->setUseDefaultResponder(value);
+}
+
+time_t OCSP::getResponseValidity() {
+ return m_impl->getResponseValidity();
+}
+
+} // namespace ValidationCore
--- /dev/null
+/*
+ * 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.
+ */
+/*!
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 0.5
+ * @file OCPS.h
+ * @brief This class is used to hide OCSP implementation.
+ */
+
+#ifndef _VALIDATION_CORE_OCSP_H_
+#define _VALIDATION_CORE_OCSP_H_
+
+#include <ctime>
+
+#include <dpl/noncopyable.h>
+
+#include <vcore/Certificate.h>
+#include <vcore/CertificateCollection.h>
+#include <vcore/VerificationStatus.h>
+
+namespace ValidationCore {
+
+class OCSPImpl;
+
+class OCSP : DPL::Noncopyable
+{
+public:
+ OCSP();
+
+ VerificationStatus checkEndEntity(const CertificateCollection &certList);
+
+ enum DigestAlgorithm
+ {
+ SHA1,
+ SHA224,
+ SHA256,
+ SHA384,
+ SHA512
+ };
+
+ /**
+ * Sets digest algorithm for certid in ocsp request
+ */
+ void setDigestAlgorithmForCertId(DigestAlgorithm alg);
+
+ /**
+ * Sets digest algorithm for certid in ocsp request
+ */
+ void setDigestAlgorithmForRequest(DigestAlgorithm alg);
+
+ void setTrustedStore(const CertificateList& certs);
+
+ VerificationStatusSet validateCertificateList(const CertificateList &certs);
+
+ VerificationStatus validateCertificate(CertificatePtr argCert,
+ CertificatePtr argIssuer);
+
+ void setDefaultResponder(const char* uri);
+
+ void setUseDefaultResponder(bool value);
+
+ /**
+ * @return time when response will become invalid - for list of
+ * certificates, this is the minimum of all validities; value is
+ * valid only for not-revoked certificates (non error validation result)
+ */
+ time_t getResponseValidity();
+
+ virtual ~OCSP();
+private:
+ OCSPImpl *m_impl;
+};
+
+} // namespace ValidationCore
+
+#endif //ifndef _VALIDATION_CORE_OCSP_H_
--- /dev/null
+/*
+ * 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.
+ */
+/*
+ * @author Michal Ciepielski(m.ciepielski@samsung.com)
+ * @version 0.3
+ * @brief
+ */
+
+#include <vcore/OCSPCertMgrUtil.h>
+#include <vcore/SSLContainers.h>
+
+#include <openssl/pem.h>
+#include <openssl/ocsp.h>
+#include <openssl/x509.h>
+#include <dpl/log/log.h>
+#include <dpl/scoped_resource.h>
+#include <string.h>
+#include <iostream>
+#include <string>
+
+#include <cert-service.h>
+
+namespace {
+const int MAX_BUF = 1024;
+
+struct ContextDeleter
+{
+ typedef CERT_CONTEXT* Type;
+ static Type NullValue()
+ {
+ return NULL;
+ }
+ static void Destroy(Type context)
+ {
+ if (context) {
+ cert_svc_cert_context_final(context);
+ }
+ }
+};
+}
+
+namespace ValidationCore {
+namespace OCSPCertMgrUtil {
+/*
+ * TODO This API function should be changed to:
+ * CertifiatePtr getCertFromStore(const std::string &subject);
+ *
+ * All of cert_svc function could return error because input
+ * data are corruped. That's why I dont want to throw exceptions
+ * in this function.
+ */
+void getCertFromStore(X509_NAME *subject,
+ X509 **xcert)
+{
+ if (!xcert || *xcert || !subject) {
+ LogError("Invalid input!");
+ return;
+ }
+
+ typedef DPL::ScopedResource<ContextDeleter> ScopedContext;
+
+ int result;
+ char buffer[MAX_BUF];
+ const unsigned char* ptr = NULL;
+ X509 *pCertificate = NULL;
+ cert_svc_filename_list *fileList = NULL;
+
+ X509_NAME_oneline(subject, buffer, MAX_BUF);
+
+ ScopedContext ctx(cert_svc_cert_context_init());
+ if (ctx.Get() == NULL) {
+ LogWarning("Error in cert_svc_cert_context_init.");
+ return;
+ }
+
+ LogDebug("Search certificate with subject: " << buffer);
+ result = cert_svc_search_certificate(ctx.Get(), SUBJECT_STR, buffer);
+ LogDebug("Search finished!");
+
+ if (CERT_SVC_ERR_NO_ERROR != result) {
+ LogWarning("Error during certificate search");
+ return;
+ }
+
+ fileList = ctx.Get()->fileNames;
+
+ if (fileList == NULL) {
+ LogDebug("No certificate found");
+ return;
+ }
+
+ if (fileList->filename == NULL) {
+ LogWarning("Empty filename");
+ return;
+ }
+
+ LogDebug("Found cert file: " << fileList->filename);
+ ScopedContext ctx2(cert_svc_cert_context_init());
+
+ if (ctx2.Get() == NULL) {
+ LogWarning("Error in cert_svc_cert_context_init.");
+ return;
+ }
+
+ // TODO add read_certifcate_from_file function to Certificate.h
+ if (CERT_SVC_ERR_NO_ERROR !=
+ cert_svc_load_file_to_context(ctx2.Get(), fileList->filename)) {
+ LogWarning("Error in cert_svc_load_file_to_context");
+ return;
+ }
+
+ ptr = ctx2.Get()->certBuf->data;
+ // create a certificate from mem buff
+ pCertificate = d2i_X509(NULL, &ptr, ctx2.Get()->certBuf->size);
+
+ if (pCertificate == NULL) {
+ LogWarning("Error during certificate conversion in d2i_X509");
+ return;
+ }
+
+ *xcert = pCertificate;
+ if (fileList->next != NULL) {
+ LogError("There is more then one certificate with same subject :/");
+ // TODO Implement me.
+ for (fileList = fileList->next;
+ fileList != NULL;
+ fileList = fileList->next) {
+ LogError(
+ "Additional certificate with same subject: " <<
+ fileList->filename);
+ }
+ }
+}
+
+CertificatePtr getParentFromStore(const CertificatePtr &certificate)
+{
+ Assert(certificate.Get());
+ X509* rawPtr = certificate->getX509();
+
+ /* TODO Add getIssuerName function to Certificate.h */
+ X509_NAME *name = X509_get_issuer_name(rawPtr);
+
+ X509* rawTemp = NULL;
+ getCertFromStore(name, &rawTemp);
+
+ if (rawTemp == NULL) {
+ return CertificatePtr();
+ }
+
+ SSLSmartContainer<X509> scope(rawTemp);
+ return CertificatePtr(new Certificate(rawTemp));
+}
+
+CertificateList completeCertificateChain(const CertificateList &certificateList)
+{
+ CertificateList result = certificateList;
+ CertificatePtr last = result.back();
+ if (last->isSignedBy(last)) {
+ return result;
+ }
+ CertificatePtr parent = getParentFromStore(last);
+ if (parent.Get()) {
+ result.push_back(parent);
+ }
+ return result;
+}
+} // namespace OCSPCertMgrUtil
+} // namespace ValidationCore
--- /dev/null
+/*
+ * 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.
+ */
+/*
+ * @author Tomasz Morawski(t.morawski@samsung.com)
+ * @author Michal Ciepielski(m.ciepielski@samsung.com)
+ * @version 0.2
+ * @brief
+ */
+
+#ifndef _OCSP_CERT_MGR_UTIL_H_
+#define _OCSP_CERT_MGR_UTIL_H_
+
+#include <vcore/Certificate.h>
+
+namespace ValidationCore {
+namespace OCSPCertMgrUtil {
+void getCertFromStore(X509_NAME *subject,
+ X509 **xcert);
+CertificatePtr getParentFromStore(const CertificatePtr &certificate);
+/*
+ * Look for "parent" certificate from store.
+ * It returns new certificate chain.
+ */
+CertificateList completeCertificateChain(const CertificateList &certList);
+} // namespace OCSPCertMgrUtil
+} // namespace ValidationCore
+#endif
+
--- /dev/null
+/*
+ * 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.
+ */
+/*!
+ * @author Tomasz Morawski(t.morawski@samsung.com)
+ * @author Michal Ciepielski(m.ciepielski@samsung.com)
+ * @author Piotr Marcinkiewicz(p.marcinkiew@samsung.com)
+ * @version 0.4
+ * @file OCPS.cpp
+ * @brief Routines for certificate validation over OCSP
+ */
+
+#include <vcore/OCSP.h>
+#include <vcore/OCSPImpl.h>
+
+#include <string.h>
+#include <algorithm>
+
+#include <openssl/ssl.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/x509v3.h>
+
+#include <dpl/log/log.h>
+#include <dpl/assert.h>
+#include <dpl/foreach.h>
+#include <dpl/scoped_array.h>
+#include <dpl/scoped_free.h>
+
+#include <libsoup/soup.h>
+
+#include <vcore/Certificate.h>
+#include <vcore/SoupMessageSendSync.h>
+
+extern "C" {
+// This function is needed to fix "Invalid conversion from void*
+// to unsigned char*" C++ compiler error during calling
+// i2d_OCSP_REQUEST_bio macro
+ extern bool convertToBuffer(OCSP_REQUEST* req,
+ char** buf,
+ int* size);
+}
+
+namespace {
+const int ConnectionTimeoutInSeconds = 6;
+const int ConnectionRetryCount = 3;
+
+//! Maximum leeway in validity period in seconds: default 1 day
+//! (@see checkRevocationStatus function code)
+
+//! Maximum validity time for revocation status (1 day)
+const int MaxValidatyPeriodInSeconds = 24 * 60 * 60;
+
+//! Max age (@see checkRevocationStatus function code)
+const int MaxAge = -1;
+} // anonymous namespace
+
+namespace ValidationCore {
+
+const char* OCSPImpl::DEFAULT_RESPONDER_URI_ENV = "OCSP_DEFAULT_RESPONDER_URI";
+
+static const EVP_MD* getDigestAlg(OCSP::DigestAlgorithm alg)
+{
+ switch (alg) {
+ case OCSP::SHA1:
+ return EVP_sha1();
+ case OCSP::SHA224:
+ return EVP_sha224();
+ case OCSP::SHA256:
+ return EVP_sha256();
+ case OCSP::SHA384:
+ return EVP_sha384();
+ case OCSP::SHA512:
+ return EVP_sha512();
+ default:
+ return NULL;
+ }
+}
+
+OCSPImpl::OCSPImpl() :
+ /* Upgrade of openssl is required to support sha256 */
+ // m_pCertIdDigestAlg(EVP_sha256()),
+ // m_pRequestDigestAlg(EVP_sha256()),
+ m_pCertIdDigestAlg(EVP_sha1()),
+ m_pRequestDigestAlg(EVP_sha1()),
+ m_bUseNonce(false),
+ m_bUseDefResponder(false),
+ m_bSignRequest(false),
+ m_pSignKey(0)
+{
+}
+
+SoupWrapper::SoupMessageSendBase::RequestStatus OCSPImpl::sendOcspRequest(
+ OCSP_REQUEST* argRequest,
+ const DPL::OptionalString& argUri)
+{
+ using namespace SoupWrapper;
+ // convert OCSP_REQUEST to memory buffer
+ std::string url = DPL::ToUTF8String(*argUri);
+ char* requestBuffer;
+ int requestSizeInt;
+ if (!convertToBuffer(argRequest, &requestBuffer, &requestSizeInt)) {
+ ThrowMsg(Exception::VerificationError,
+ "OCSP: failed to convert OCSP_REQUEST to mem buffer");
+ }
+
+ Assert(requestSizeInt >= 0);
+
+ SoupMessageSendBase::MessageBuffer buffer;
+ buffer.resize(requestSizeInt);
+ memcpy(&buffer[0], requestBuffer, requestSizeInt);
+ free(requestBuffer);
+
+ char *cport = 0,*chost = 0,*cpath = 0;
+ int use_ssl = 0;
+
+ if (!OCSP_parse_url(const_cast<char*>(url.c_str()),
+ &chost,
+ &cport,
+ &cpath,
+ &use_ssl))
+ {
+ LogWarning("Error in OCSP_parse_url");
+ return SoupMessageSendBase::REQUEST_STATUS_CONNECTION_ERROR;
+ }
+
+ std::string host = chost;
+
+ if (cport) {
+ host += ":";
+ host += cport;
+ }
+
+ free(cport);
+ free(chost);
+ free(cpath);
+
+ m_soupMessage.setHost(url);
+ m_soupMessage.setHeader("Host", host);
+ m_soupMessage.setRequest(std::string("application/ocsp-request"),
+ buffer);
+
+ return m_soupMessage.sendSync();
+}
+
+ValidationCore::VerificationStatusSet OCSPImpl::validateCertificateList(
+ const CertificateList &certs)
+{
+ VerificationStatusSet statusSet;
+
+ if (certs.size() < 2) {
+ // no certificates to verify, just return a error
+ LogWarning("No validation will be proceed. OCSP require at"
+ " least 2 certificates in chain. Found only " <<
+ certs.size());
+ statusSet.add(VERIFICATION_STATUS_ERROR);
+ return statusSet;
+ }
+
+ CertificateList::const_iterator iter = certs.begin();
+ CertificateList::const_iterator parent = iter;
+
+ time_t minValidity = 0;
+ for (++parent; parent != certs.end(); ++iter, ++parent) {
+ LogDebug("Certificate validation (CN:" <<
+ (*iter)->getOneLine() << ")");
+ LogDebug("Parent certificate (CN:" <<
+ (*parent)->getOneLine() << ")");
+ statusSet.add(validateCertificate(*iter, *parent));
+ if ((0 == minValidity || minValidity > m_responseValidity) &&
+ m_responseValidity > 0)
+ {
+ minValidity = m_responseValidity;
+ }
+ }
+ m_responseValidity = minValidity;
+
+ return statusSet;
+}
+
+VerificationStatus OCSPImpl::checkEndEntity(
+ const CertificateCollection &chain)
+{
+ const char *defResponderURI = getenv(OCSPImpl::DEFAULT_RESPONDER_URI_ENV);
+
+ VerificationStatusSet verSet;
+ if (defResponderURI) {
+ setUseDefaultResponder(true);
+ setDefaultResponder(defResponderURI);
+ }
+
+ // this is temporary fix. it must be rewriten
+ CertificateList clst;
+ if (chain.isChain() && chain.size() >= 2) {
+ CertificateList::const_iterator icert = chain.begin();
+ clst.push_back(*icert);
+ ++icert;
+ clst.push_back(*icert);
+ }
+ verSet += validateCertificateList(clst);
+
+ return verSet.convertToStatus();
+}
+
+VerificationStatus OCSPImpl::validateCertificate(CertificatePtr argCert,
+ CertificatePtr argIssuer)
+{
+ using namespace SoupWrapper;
+
+ Assert(!!argCert);
+ Assert(!!argIssuer);
+
+ Try {
+ DPL::OptionalString uri;
+
+ if (!m_bUseDefResponder) {
+ uri = argCert->getOCSPURL();
+ if (!uri) {
+ return VERIFICATION_STATUS_NOT_SUPPORT;
+ }
+ } else {
+ if (m_strResponderURI.empty()) {
+ ThrowMsg(Exception::VerificationError,
+ "Default responder is not set");
+ }
+ LogWarning("Default responder will be used");
+
+ uri = m_strResponderURI;
+ }
+
+ // creates a request
+ CreateRequestResult newRequest = createRequest(argCert, argIssuer);
+ if (!newRequest.success) {
+ ThrowMsg(Exception::VerificationError, "Request creation failed");
+ }
+
+ // SSLSmartContainer <OCSP_CERTID> certIdCont(certId);
+ // this smart ptr is commented out in purpose. request
+ // manages certIdmemory (which was done in createRequest above)
+ SSLSmartContainer <OCSP_REQUEST> requestCont(newRequest.ocspRequest);
+
+ SoupMessageSendBase::RequestStatus requestStatus;
+ requestStatus = sendOcspRequest(requestCont, uri);
+
+ if (requestStatus != SoupMessageSendBase::REQUEST_STATUS_OK) {
+ return VERIFICATION_STATUS_CONNECTION_FAILED;
+ }
+
+ // Response is m_soupMessage, convert it to OCSP_RESPONSE
+ OcspResponse response = convertToResponse();
+
+ if (!response.first) {
+ ThrowMsg(OCSPImpl::Exception::VerificationError,
+ "OCSP: failed to convert mem buffer to OCSP_RESPONSE");
+ }
+
+ SSLSmartContainer <OCSP_RESPONSE> responseCont(response.second);
+ // verify response eg. check response status,
+ // validate responder certificate
+ validateResponse(requestCont,
+ responseCont,
+ newRequest.ocspCertId);
+ } Catch(Exception::ConnectionError) {
+ LogWarning("OCSP: ConnectionError");
+ return VERIFICATION_STATUS_CONNECTION_FAILED;
+ } Catch(Exception::CertificateRevoked) {
+ LogWarning("OCSP: Revoked");
+ return VERIFICATION_STATUS_REVOKED;
+ } Catch(Exception::CertificateUnknown) {
+ LogWarning("OCSP: Unknown");
+ return VERIFICATION_STATUS_UNKNOWN;
+ } Catch(Exception::VerificationError) {
+ LogWarning("OCSP: Verification error");
+ return VERIFICATION_STATUS_VERIFICATION_ERROR;
+ } Catch(Exception::Base) {
+ LogWarning("OCSP: Error");
+ return VERIFICATION_STATUS_ERROR;
+ }
+ LogWarning("OCSP: Good");
+ return VERIFICATION_STATUS_GOOD;
+}
+
+OCSPImpl::CreateRequestResult OCSPImpl::createRequest(CertificatePtr argCert,
+ CertificatePtr argIssuer)
+{
+ OCSP_REQUEST* newRequest = OCSP_REQUEST_new();
+
+ if (!newRequest) {
+ LogWarning("OCSP: Failed to create a request");
+ return CreateRequestResult();
+ }
+
+ SSLSmartContainer <OCSP_REQUEST> requestCont(newRequest);
+
+ OCSP_CERTID* certId = addSerial(argCert, argIssuer);
+
+ if (!certId) {
+ LogWarning("OCSP: Unable to create a serial id");
+ return CreateRequestResult();
+ }
+ SSLSmartContainer <OCSP_CERTID> certIdCont(certId);
+
+ // Inserting certificate ID to request
+ if (!OCSP_request_add0_id(requestCont, certIdCont)) {
+ LogWarning("OCSP: Unable to create a certificate id");
+ return CreateRequestResult();
+ }
+
+ if (m_bUseNonce) {
+ OCSP_request_add1_nonce(requestCont, 0, -1);
+ }
+
+ if (m_bSignRequest) {
+ if (!m_pSignCert || !m_pSignKey) {
+ LogWarning("OCSP: Unable to sign request if "
+ "SignCert or SignKey was not set");
+ return CreateRequestResult();
+ }
+
+ if (!OCSP_request_sign(requestCont,
+ m_pSignCert->getX509(),
+ m_pSignKey,
+ m_pRequestDigestAlg,
+ 0,
+ 0))
+ {
+ LogWarning("OCSP: Unable to sign request");
+ return CreateRequestResult();
+ }
+ }
+ return CreateRequestResult(true,
+ requestCont.DetachPtr(),
+ certIdCont.DetachPtr());
+}
+
+OCSP_CERTID* OCSPImpl::addSerial(CertificatePtr argCert,
+ CertificatePtr argIssuer)
+{
+ X509_NAME* iname = X509_get_subject_name(argIssuer->getX509());
+ ASN1_BIT_STRING* ikey = X509_get0_pubkey_bitstr(argIssuer->getX509());
+ ASN1_INTEGER* serial = X509_get_serialNumber(argCert->getX509());
+
+ return OCSP_cert_id_new(m_pCertIdDigestAlg, iname, ikey, serial);
+}
+
+void OCSPImpl::setDigestAlgorithmForCertId(OCSP::DigestAlgorithm alg)
+{
+ const EVP_MD* foundAlg = getDigestAlg(alg);
+
+ if (NULL != foundAlg) {
+ m_pCertIdDigestAlg = foundAlg;
+ } else {
+ LogDebug("Request for unsupported CertId digest algorithm"
+ "ignored!");
+ }
+}
+
+void OCSPImpl::setDigestAlgorithmForRequest(OCSP::DigestAlgorithm alg)
+{
+ const EVP_MD* foundAlg = getDigestAlg(alg);
+
+ if (NULL != foundAlg) {
+ m_pRequestDigestAlg = foundAlg;
+ } else {
+ LogDebug("Request for unsupported OCSP request digest algorithm"
+ "ignored!");
+ }
+}
+
+void OCSPImpl::setTrustedStore(const CertificateList& certs)
+{
+ X509_STORE *store = X509_STORE_new();
+ m_pTrustedStore = store;
+ // create a trusted store basing on certificate chain from a signature
+ FOREACH(iter, certs) {
+ X509_STORE_add_cert(store, (*iter)->getX509());
+ }
+}
+
+void OCSPImpl::validateResponse(OCSP_REQUEST* argRequest,
+ OCSP_RESPONSE* argResponse,
+ OCSP_CERTID* argCertId)
+{
+ int result = OCSP_response_status(argResponse);
+
+ if (result != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
+ handleInvalidResponse(result);
+ ThrowMsg(Exception::VerificationError, "OCSP_response_status failed");
+ }
+
+ // get response object
+ OCSP_BASICRESP* basic = OCSP_response_get1_basic(argResponse);
+ if (!basic) {
+ ThrowMsg(Exception::VerificationError,
+ "OCSP: Unable to get a BASICRESP object.");
+ }
+
+ SSLSmartContainer <OCSP_BASICRESP> basicRespCont(basic);
+ if (m_bUseNonce && OCSP_check_nonce(argRequest, basicRespCont) <= 0) {
+ ThrowMsg(Exception::VerificationError, "OCSP: Invalid nonce");
+ }
+
+ if (!verifyResponse(basic)) {
+ ThrowMsg(Exception::VerificationError,
+ "Unable to verify the OCSP responder's certificate");
+ }
+
+ checkRevocationStatus(basicRespCont, argCertId);
+}
+
+bool OCSPImpl::verifyResponse(OCSP_BASICRESP* basic)
+{
+ Assert(m_pTrustedStore);
+ // verify ocsp response
+ int response = OCSP_basic_verify(basic, NULL, m_pTrustedStore, 0);
+ if (response <= 0) {
+ LogWarning("OCSP verification failed");
+ }
+
+ return response > 0;
+}
+
+void OCSPImpl::checkRevocationStatus(OCSP_BASICRESP* basic,
+ OCSP_CERTID* id)
+{
+ ASN1_GENERALIZEDTIME* producedAt;
+ ASN1_GENERALIZEDTIME* thisUpdate;
+ ASN1_GENERALIZEDTIME* nextUpdate;
+ int reason;
+ int status;
+
+ m_responseValidity = 0;
+
+ if (!OCSP_resp_find_status(basic,
+ id,
+ &status,
+ &reason,
+ &producedAt,
+ &thisUpdate,
+ &nextUpdate))
+ {
+ ThrowMsg(Exception::VerificationError,
+ "OCSP: Failed to find certificate status.");
+ }
+
+ if (!OCSP_check_validity(thisUpdate,
+ nextUpdate,
+ MaxValidatyPeriodInSeconds,
+ MaxAge))
+ {
+ ThrowMsg(Exception::VerificationError,
+ "OCSP: Failed to check certificate validate.");
+ }
+
+ if (nextUpdate) {
+ asn1GeneralizedTimeToTimeT(nextUpdate,&m_responseValidity);
+ time_t now;
+ time(&now);
+ LogDebug("Time of next OCSP update got from server: " <<
+ m_responseValidity);
+ LogDebug("Expires in: " << (m_responseValidity - now));
+ LogDebug("Original: " << nextUpdate->data);
+ }
+
+ switch (status) {
+ case V_OCSP_CERTSTATUS_GOOD:
+ return;
+ case V_OCSP_CERTSTATUS_REVOKED:
+ ThrowMsg(Exception::CertificateRevoked, "Certificate is Revoked");
+ case V_OCSP_CERTSTATUS_UNKNOWN:
+ ThrowMsg(Exception::CertificateUnknown, "Certificate is Unknown");
+ default:
+ Assert(false && "Invalid status");
+ }
+}
+
+OCSPImpl::OcspResponse OCSPImpl::convertToResponse()
+{
+ using namespace SoupWrapper;
+
+ // convert memory buffer to ocsp response object
+ BUF_MEM res_bmem;
+ OCSP_RESPONSE* response;
+
+ SoupMessageSendBase::MessageBuffer buffer = m_soupMessage.getResponse();
+
+ res_bmem.length = buffer.size();
+ res_bmem.data = &buffer[0];
+ res_bmem.max = buffer.size();
+
+ BIO* res_mem_bio = BIO_new(BIO_s_mem());
+ BIO_set_mem_buf(res_mem_bio, &res_bmem, BIO_NOCLOSE);
+
+ response = d2i_OCSP_RESPONSE_bio(res_mem_bio, NULL);
+ BIO_free_all(res_mem_bio);
+
+ if (!response) {
+ LogWarning("OCSP: Failed to convert OCSP Response to DER format");
+ return std::make_pair(false, static_cast<OCSP_RESPONSE*>(NULL));
+ }
+
+ return std::make_pair(true, response);
+}
+
+void OCSPImpl::handleInvalidResponse(int result)
+{
+ switch (result) {
+ case OCSP_RESPONSE_STATUS_MALFORMEDREQUEST:
+ LogWarning("OCSP: Server returns "
+ "OCSP_RESPONSE_STATUS_MALFORMEDREQUEST status");
+ break;
+ case OCSP_RESPONSE_STATUS_INTERNALERROR:
+ LogWarning("OCSP: Server returns "
+ "OCSP_RESPONSE_STATUS_INTERNALERROR status");
+ break;
+ case OCSP_RESPONSE_STATUS_TRYLATER:
+ LogWarning("OCSP: Server returns "
+ "OCSP_RESPONSE_STATUS_TRYLATER status");
+ break;
+ case OCSP_RESPONSE_STATUS_SIGREQUIRED:
+ LogWarning("OCSP: Server returns "
+ "OCSP_RESPONSE_STATUS_SIGREQUIRED status");
+ break;
+ case OCSP_RESPONSE_STATUS_UNAUTHORIZED:
+ LogWarning("OCSP: Server returns "
+ "OCSP_RESPONSE_STATUS_UNAUTHORIZED status");
+ break;
+ default:
+ Assert(false && "Invalid result value");
+ }
+}
+} // namespace ValidationCore
--- /dev/null
+/*
+ * 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.
+ */
+/*!
+ * @author Tomasz Morawski(t.morawski@samsung.com)
+ * @author Michal Ciepielski(m.ciepielski@samsung.com)
+ * @author Piotr Marcinkiewicz(p.marcinkiew@samsung.com)
+ * @author Bartlomiej Grzelewski(b.grzelewski@samsung.com)
+ * @version 0.4
+ * @file OCPS.h
+ * @brief Routines for certificate validation over OCSP
+ */
+
+#ifndef _VALIDATION_CORE_OCSPIMPL_H_
+#define _VALIDATION_CORE_OCSPIMPL_H_
+
+#include <vcore/OCSP.h>
+
+#include <string>
+#include <vector>
+#include <list>
+
+#include <openssl/pem.h>
+#include <openssl/ocsp.h>
+#include <libsoup/soup.h>
+
+#include <dpl/assert.h>
+#include <dpl/exception.h>
+#include <dpl/optional_typedefs.h>
+
+#include <vcore/scoped_gpointer.h>
+#include <vcore/OCSPCertMgrUtil.h>
+#include <vcore/CertificateCollection.h>
+#include <vcore/CertificateStorage.h>
+#include <vcore/VerificationStatus.h>
+#include <vcore/SSLContainers.h>
+#include <vcore/SoupMessageSendBase.h>
+#include <vcore/SoupMessageSendSync.h>
+#include <vcore/TimeConversion.h>
+/*
+ * The WRT MUST NOT allow installation of widgets with revoked signatures.
+ *
+ * The WRT MUST NOT allow use of widgets with revoked signatures.
+ *
+ * The WRT MUST support checking for revocation of widget signatures via
+ * OCSP [RFC 2560] at widget installation time, according to the following:
+ *
+ * At widget installation time, the WRT shall make several attempts
+ * (5 attempts at 6 seconds apart recommended) to establish contact with
+ * the OCSP server.
+ *
+ * If connectivity is successful and the application is validated, the
+ * installation process shall continue.
+ *
+ * If connectivity is successful and if the widget signature is
+ * determined to be revoked, the WRT shall issue a suitable error message
+ * and cancel installation.
+ *
+ * If connectivity is successful and revocation status is unknown or if
+ * connectivity is unsuccessful, the user must be notified that the
+ * widget was unable to be installed as trusted - the certification of
+ * the widget signature has not been validated -, and prompt the user to allow
+ * the user to install the widget as an untrusted application, or reject
+ * the installation.
+ *
+ * The WRT MUST support checking for revocation of widget signatures via OCSP
+ * [RFC 2560] at widget runtime.
+ *
+ * The WRT MUST support OCSP access policy.
+ */
+
+namespace ValidationCore {
+
+class OCSPImpl
+{
+ public:
+ static const char* DEFAULT_RESPONDER_URI_ENV;
+
+ VerificationStatus checkEndEntity(const CertificateCollection &certList);
+ OCSPImpl();
+
+ /**
+ * Sets digest algorithm for certid in ocsp request
+ */
+ void setDigestAlgorithmForCertId(OCSP::DigestAlgorithm alg);
+
+ /**
+ * Sets digest algorithm for certid in ocsp request
+ */
+ void setDigestAlgorithmForRequest(OCSP::DigestAlgorithm alg);
+
+ void setTrustedStore(const CertificateList& certs);
+
+ VerificationStatusSet validateCertificateList(const CertificateList &certs);
+
+ VerificationStatus validateCertificate(CertificatePtr argCert,
+ CertificatePtr argIssuer);
+
+ void setDefaultResponder(const char* uri)
+ {
+ Assert(uri);
+ m_strResponderURI = DPL::FromUTF8String(uri);
+ }
+
+ void setUseDefaultResponder(bool value)
+ {
+ m_bUseDefResponder = value;
+ }
+
+ /**
+ * @return time when response will become invalid - for list of
+ * certificates, this is the minimum of all validities; value is
+ * valid only for not-revoked certificates (non error validation result)
+ */
+ time_t getResponseValidity()
+ {
+ return m_responseValidity;
+ }
+
+ private:
+ typedef WRT::ScopedGPointer<SoupSession> ScopedSoupSession;
+ typedef WRT::ScopedGPointer<SoupMessage> ScopedSoupMessage;
+
+ void handleInvalidResponse(int result);
+ void sendHTTPRequest(ScopedSoupSession& session,
+ ScopedSoupMessage& msg,
+ const char* host,
+ const char* port,
+ const char* path,
+ char* requestBuffer,
+ size_t reqestSize);
+ void sendRequest(const std::string& uri,
+ char* requestBuffer,
+ size_t requestSize,
+ char** responseBuffer,
+ size_t* responseSize);
+
+ class Exception
+ {
+ public:
+ DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
+ DECLARE_EXCEPTION_TYPE(Base, ConnectionError)
+ DECLARE_EXCEPTION_TYPE(Base, CertificateRevoked)
+ DECLARE_EXCEPTION_TYPE(Base, CertificateUnknown)
+ DECLARE_EXCEPTION_TYPE(Base, VerificationError)
+ DECLARE_EXCEPTION_TYPE(Base, RetrieveCertFromStoreError)
+ DECLARE_EXCEPTION_TYPE(Base, VerificationNotSupport)
+ };
+
+ const EVP_MD* m_pCertIdDigestAlg;
+ const EVP_MD* m_pRequestDigestAlg;
+
+ typedef std::pair<char*, size_t> HttpResponseBuffer;
+
+ SoupWrapper::SoupMessageSendBase::RequestStatus sendOcspRequest(
+ OCSP_REQUEST* argRequest,
+ const DPL::OptionalString& argUri);
+
+ //! Validates a single certificate
+ /*!
+ * @param cert The certificate to check
+ * @param issuer A certificate used to sign the certificate to check.
+ */
+
+ struct CreateRequestResult
+ {
+ bool success;
+ OCSP_REQUEST* ocspRequest;
+ OCSP_CERTID* ocspCertId;
+ CreateRequestResult(bool argSuccess = false,
+ OCSP_REQUEST* argOcspRequest = NULL,
+ OCSP_CERTID* argOcspCertId = NULL) :
+ success(argSuccess),
+ ocspRequest(argOcspRequest),
+ ocspCertId(argOcspCertId)
+ {
+ }
+ };
+
+ //! Creates a OCSP request
+ /*!
+ * @param request Returns created OCSP_REQUEST
+ * @param id Returns CertId that is used to find proper OCSP result in
+ * the OCSP response (@see checkRevocationStatus for more details).
+ *
+ */
+ CreateRequestResult createRequest(CertificatePtr argCert,
+ CertificatePtr argIssuer);
+
+ OCSP_CERTID* addSerial(CertificatePtr argCert,
+ CertificatePtr argIssuer);
+
+ void validateResponse(OCSP_REQUEST* argRequest,
+ OCSP_RESPONSE* argResponse,
+ OCSP_CERTID* argCertId);
+
+ //! Create a X509 store
+ bool verifyResponse(OCSP_BASICRESP* argResponse);
+
+ void checkRevocationStatus(OCSP_BASICRESP* argBasicResponse,
+ OCSP_CERTID* argCertId);
+
+ typedef std::pair<bool, OCSP_RESPONSE*> OcspResponse;
+
+ OcspResponse convertToResponse();
+
+ time_t m_responseValidity;
+ bool m_bUseNonce;
+ bool m_bUseDefResponder;
+ DPL::String m_strResponderURI;
+ bool m_bSignRequest;
+ EVP_PKEY* m_pSignKey;
+ CertificatePtr m_pSignCert;
+ SSLSmartContainer <X509_STORE> m_pTrustedStore;
+ SoupWrapper::SoupMessageSendSync m_soupMessage;
+};
+
+} // ValidationCore
+
+#endif // _VALIDATION_CORE_OCSPIMPL_H_
--- /dev/null
+/*
+ * 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.
+ */
+/*
+ * @author Tomasz Morawski(t.morawski@samsung.com)
+ * @version 0.1
+ * @brief
+ */
+
+#include <openssl/ocsp.h>
+
+/*
+ * This function is needed to fix "Invalid conversion from void* to unsigned char*"
+ * C++ compiler error during calling i2d_OCSP_REQUEST_bio macro
+ */
+int convertToBuffer(OCSP_REQUEST *req, char **buf, int *size) {
+ BIO *req_mem_bio;
+ BUF_MEM req_bmem;
+
+ /*
+ * size and membuffer for request
+ */
+ *size = i2d_OCSP_REQUEST(req, NULL);
+ *buf = (char*) malloc(*size);
+
+ if (!*buf)
+ return 0;
+
+ /* copy request into buffer */
+ req_bmem.length = 0;
+ req_bmem.data = *buf;
+ req_bmem.max = *size;
+
+ /*
+ * create a new buffer using openssl
+ */
+ req_mem_bio = BIO_new(BIO_s_mem());
+
+ if (!req_mem_bio) {
+ /*
+ * creation failed, return
+ */
+ free(*buf);
+ *buf = NULL;
+ return 0;
+ }
+
+ BIO_set_mem_buf(req_mem_bio, &req_bmem, BIO_NOCLOSE);
+
+ /*
+ * prepare request
+ */
+ if (i2d_OCSP_REQUEST_bio(req_mem_bio, req) <= 0) {
+ free(*buf);
+ *buf = NULL;
+ BIO_free_all(req_mem_bio);
+ return 0;
+ }
+
+ /*
+ * check consistency
+ */
+ if (*size != ((int)req_bmem.length) || req_bmem.length != req_bmem.max)
+ {
+ free(*buf);
+ *buf = NULL;
+ BIO_free_all(req_mem_bio);
+ return 0;
+ }
+
+ /*
+ * free all reserved memory
+ */
+ BIO_free_all(req_mem_bio);
+
+ /*
+ * and return success
+ */
+ return 1;
+}
--- /dev/null
+/*
+ * 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 ParserSchema.h
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief
+ */
+#ifndef _PARSERSCHEMA_H_
+#define _PARSERSCHEMA_H_
+
+#include <map>
+#include <string>
+
+#include <dpl/log/log.h>
+
+#include <vcore/SaxReader.h>
+
+namespace ValidationCore {
+namespace ParserSchemaException {
+DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
+DECLARE_EXCEPTION_TYPE(Base, XmlReaderError)
+DECLARE_EXCEPTION_TYPE(Base, CertificateLoaderError)
+DECLARE_EXCEPTION_TYPE(Base, UnsupportedAlgorithm)
+DECLARE_EXCEPTION_TYPE(Base, UnsupportedValue)
+}
+
+template<typename ParserType, typename DataType>
+class ParserSchema
+{
+ public:
+ struct TagDescription
+ {
+ TagDescription(const std::string &tag,
+ const std::string & xmlNamespace) :
+ tagName(tag),
+ namespaceUri(xmlNamespace)
+ {
+ }
+
+ std::string tagName;
+ std::string namespaceUri;
+
+ bool operator<(const TagDescription &second) const
+ {
+ if (tagName < second.tagName) {
+ return true;
+ }
+ if (tagName > second.tagName) {
+ return false;
+ }
+ if (namespaceUri < second.namespaceUri) {
+ return true;
+ }
+ return false;
+ }
+ };
+
+ ParserSchema(ParserType * parser) :
+ m_functions(parser)
+ {
+ }
+
+ virtual ~ParserSchema()
+ {
+ }
+
+ void initialize(const std::string &filename,
+ bool defaultArgs,
+ SaxReader::ValidationType valType,
+ const std::string &xmlschema)
+ {
+ Try
+ {
+ m_reader.initialize(filename, defaultArgs, valType, xmlschema);
+ }
+ Catch(SaxReader::Exception::Base)
+ {
+ ReThrowMsg(ParserSchemaException::XmlReaderError, "XmlReaderError");
+ }
+ }
+
+ void deinitialize()
+ {
+ m_reader.deinitialize();
+ }
+
+ void read(DataType &dataContainer)
+ {
+ Try {
+ while (m_reader.next()) {
+ switch (m_reader.type()) {
+ case SaxReader::NODE_BEGIN:
+ beginNode(dataContainer);
+ break;
+ case SaxReader::NODE_END:
+ endNode(dataContainer);
+ break;
+ case SaxReader::NODE_TEXT:
+ textNode(dataContainer);
+ break;
+ default:
+ // LogInfo("Unknown Type Node");
+ break;
+ }
+ }
+ }
+ Catch(SaxReader::Exception::Base)
+ {
+ ReThrowMsg(ParserSchemaException::XmlReaderError, "XmlReaderError");
+ }
+ }
+
+ typedef void (ParserType::*FunctionPtr)(DataType &data);
+ typedef std::map<TagDescription, FunctionPtr> FunctionMap;
+
+ void addBeginTagCallback(const std::string &tag,
+ const std::string &namespaceUri,
+ FunctionPtr function)
+ {
+ TagDescription desc(tag, namespaceUri);
+ m_beginFunctionMap[desc] = function;
+ }
+
+ void addEndTagCallback(const std::string &tag,
+ const std::string &namespaceUri,
+ FunctionPtr function)
+ {
+ TagDescription desc(tag, namespaceUri);
+ m_endFunctionMap[desc] = function;
+ }
+
+ SaxReader& getReader(void)
+ {
+ return m_reader;
+ }
+
+ std::string& getText(void)
+ {
+ return m_textNode;
+ }
+
+ protected:
+ void beginNode(DataType &dataContainer)
+ {
+ TagDescription desc(m_reader.name(), m_reader.namespaceURI());
+ FunctionPtr fun = m_beginFunctionMap[desc];
+
+ if (fun == 0) {
+ LogDebug("No function found for xml tag: " << m_reader.name());
+ return;
+ }
+
+ (m_functions->*fun)(dataContainer);
+ }
+
+ void endNode(DataType &dataContainer)
+ {
+ TagDescription desc(m_reader.name(), m_reader.namespaceURI());
+ FunctionPtr fun = m_endFunctionMap[desc];
+
+ if (fun == 0) {
+ LogDebug("No function found for xml tag: " << m_reader.name());
+ return;
+ }
+
+ (m_functions->*fun)(dataContainer);
+ }
+
+ void textNode(DataType &dataContainer)
+ {
+ (void)dataContainer;
+ m_textNode = m_reader.value();
+ }
+
+ ParserType *m_functions;
+
+ SaxReader m_reader;
+ FunctionMap m_beginFunctionMap;
+ FunctionMap m_endFunctionMap;
+
+ // temporary values require due parsing textNode
+ std::string m_textNode;
+};
+} // namespace ValidationCore
+#endif
--- /dev/null
+/*
+ * 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.
+ */
+/*
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @file ReferenceValidator.cpp
+ * @version 1.0
+ * @brief Compare signature reference list and list of widget file.
+ */
+#include <vcore/ReferenceValidator.h>
+
+#include <dirent.h>
+#include <errno.h>
+#include <fstream>
+#include <memory>
+
+#include <pcrecpp.h>
+
+#include <dpl/errno_string.h>
+#include <dpl/log/log.h>
+
+namespace {
+
+const char *SPECIAL_SYMBOL_CURRENT_DIR = ".";
+const char *SPECIAL_SYMBOL_UPPER_DIR = "..";
+const char *SPECIAL_SYMBOL_AUTHOR_SIGNATURE_FILE = "author-signature.xml";
+const char *REGEXP_DISTRIBUTOR_SIGNATURE = "^signature[1-9][0-9]*\\.xml";
+
+const char MARK_ENCODED_CHAR = '%';
+
+} // namespace anonymous
+
+namespace ValidationCore {
+
+class ReferenceValidator::Impl
+{
+ public:
+ Impl(const std::string &dirpath)
+ : m_dirpath(dirpath)
+ , m_signatureRegexp(REGEXP_DISTRIBUTOR_SIGNATURE)
+ {}
+
+ virtual ~Impl(){}
+
+ Result checkReferences(const SignatureData &signatureData){
+ const ReferenceSet &refSet = signatureData.getReferenceSet();
+ ReferenceSet refDecoded;
+
+ try {
+ for (auto it = refSet.begin(); it != refSet.end(); ++it) {
+ if (std::string::npos != it->find(MARK_ENCODED_CHAR))
+ refDecoded.insert(decodeProcent(*it));
+ else
+ refDecoded.insert(*it);
+ }
+ } catch (Result &) {
+ return ERROR_DECODING_URL;
+ }
+ return dfsCheckDirectories(
+ refDecoded,
+ std::string(),
+ signatureData.isAuthorSignature());
+ }
+
+ private:
+ int hexToInt(char hex);
+ std::string decodeProcent(const std::string &path);
+
+ Result dfsCheckDirectories(
+ const ReferenceSet &referenceSet,
+ const std::string &directory,
+ bool isAuthorSignature);
+
+ inline bool isDistributorSignature(const char *cstring) const
+ {
+ return m_signatureRegexp.FullMatch(cstring);
+ }
+
+ std::string m_dirpath;
+ std::string m_errorDescription;
+ pcrecpp::RE m_signatureRegexp;
+};
+
+int ReferenceValidator::Impl::hexToInt(char a) {
+ if (a >= '0' && a <= '9') return a-'0';
+ if (a >= 'A' && a <= 'F') return a-'A' + 10;
+ if (a >= 'a' && a <= 'f') return a-'a' + 10;
+ LogError("Symbol '" << a << "' is out of scope.");
+ throw ERROR_DECODING_URL;
+}
+
+std::string ReferenceValidator::Impl::decodeProcent(const std::string &path) {
+ std::vector<int> input(path.begin(), path.end());
+ std::vector<char> output;
+ try {
+ size_t i = 0;
+ while(i<input.size()) {
+ if (MARK_ENCODED_CHAR == input[i]) {
+ if (i+2 >= input.size())
+ throw ERROR_DECODING_URL;
+
+ int result = hexToInt(input[i+1])*16 + hexToInt(input[i+2]);
+
+ // RFC 1738 - octets 80 to FF are not allowed
+ if (result >= 128)
+ throw ERROR_DECODING_URL;
+
+ output.push_back(static_cast<char>(result));
+ i+=3;
+ } else {
+ output.push_back(static_cast<char>(input[i]));
+ ++i;
+ }
+ }
+ } catch (Result &) {
+ LogError("Error while decoding url path: " << path);
+ throw ERROR_DECODING_URL;
+ }
+ return std::string(output.begin(), output.end());
+}
+
+ReferenceValidator::Result ReferenceValidator::Impl::dfsCheckDirectories(
+ const ReferenceSet &referenceSet,
+ const std::string &directory,
+ bool isAuthorSignature)
+{
+ DIR *dp;
+ struct dirent *dirp;
+ std::string currentDir = m_dirpath + directory;
+
+ if ((dp = opendir(currentDir.c_str())) == NULL) {
+ LogError("Error opening directory: " << currentDir.c_str());
+ m_errorDescription = currentDir;
+ return ERROR_OPENING_DIR;
+ }
+
+ for (errno = 0; (dirp = readdir(dp)) != NULL; errno = 0) {
+ if (!strcmp(dirp->d_name, SPECIAL_SYMBOL_CURRENT_DIR)) {
+ continue;
+ }
+
+ if (!strcmp(dirp->d_name, SPECIAL_SYMBOL_UPPER_DIR)) {
+ continue;
+ }
+
+ if (currentDir == m_dirpath && dirp->d_type == DT_REG &&
+ !strcmp(dirp->d_name, SPECIAL_SYMBOL_AUTHOR_SIGNATURE_FILE) &&
+ isAuthorSignature)
+ {
+ continue;
+ }
+
+ if (currentDir == m_dirpath && dirp->d_type == DT_REG &&
+ isDistributorSignature(dirp->d_name)) {
+ continue;
+ }
+
+ if (dirp->d_type == DT_DIR) {
+ LogDebug("Open directory: " << (directory + dirp->d_name));
+ std::string tmp_directory = directory + dirp->d_name + "/";
+ Result result = dfsCheckDirectories(referenceSet,
+ tmp_directory,
+ isAuthorSignature);
+ if (result != NO_ERROR) {
+ closedir(dp);
+ return result;
+ }
+ } else if (dirp->d_type == DT_REG) {
+ LogDebug("Found file: " << (directory + dirp->d_name));
+
+ if (referenceSet.end() ==
+ referenceSet.find(directory + dirp->d_name))
+ {
+ closedir(dp);
+ m_errorDescription = directory + dirp->d_name;
+ return ERROR_REFERENCE_NOT_FOUND;
+ }
+ } else {
+ LogError("Unknown file type.");
+ closedir(dp);
+ m_errorDescription = directory + dirp->d_name;
+ return ERROR_UNSUPPORTED_FILE_TYPE;
+ }
+ }
+
+ if (errno != 0) {
+ m_errorDescription = DPL::GetErrnoString();
+ LogError("readdir failed. Errno code: " << errno <<
+ " Description: " << m_errorDescription);
+ closedir(dp);
+ return ERROR_READING_DIR;
+ }
+
+ closedir(dp);
+
+ return NO_ERROR;
+}
+
+ReferenceValidator::ReferenceValidator(const std::string &dirpath)
+ : m_impl(new Impl(dirpath))
+{}
+
+ReferenceValidator::~ReferenceValidator(){
+ delete m_impl;
+}
+
+ReferenceValidator::Result ReferenceValidator::checkReferences(
+ const SignatureData &signatureData)
+{
+ return m_impl->checkReferences(signatureData);
+}
+
+} // ValidationCore
--- /dev/null
+/*
+ * 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.
+ */
+/*
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @file ReferenceValidator.h
+ * @version 1.0
+ * @brief Compare signature reference list with widget package.
+ */
+#ifndef _VALIDATION_CORE_REFERENCEVALIDATOR_H_
+#define _VALIDATION_CORE_REFERENCEVALIDATOR_H_
+
+#include <dpl/noncopyable.h>
+
+#include <vcore/SignatureData.h>
+
+namespace ValidationCore {
+
+class ReferenceValidator : DPL::Noncopyable
+{
+ public:
+ enum Result
+ {
+ NO_ERROR = 0,
+ ERROR_OPENING_DIR,
+ ERROR_READING_DIR,
+ ERROR_UNSUPPORTED_FILE_TYPE,
+ ERROR_REFERENCE_NOT_FOUND,
+ ERROR_DECODING_URL
+ };
+
+ ReferenceValidator(const std::string &dirpath);
+
+ virtual ~ReferenceValidator();
+
+ Result checkReferences(const SignatureData &signatureData);
+
+ private:
+ class Impl;
+ Impl *m_impl;
+};
+}
+
+#endif // _VALIDATION_CORE_REFERENCEVALIDATOR_H_
--- /dev/null
+/*
+ * 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.
+ */
+/*!
+ * @author Piotr Marcinkiewicz(p.marcinkiew@samsung.com)
+ * @version 0.4
+ * @file CommonCertValidator.cpp
+ * @brief Common routines for certificate validation over OCSP and CRL
+ */
+
+#include "RevocationCheckerBase.h"
+
+#include <cstdlib>
+
+#include <openssl/pem.h>
+
+#include <dpl/scoped_fclose.h>
+
+#include "Certificate.h"
+#include "CertificateCollection.h"
+
+namespace {
+const char DefaultBundlePatch[] = "/opt/etc/ssl/certs/ca-certificates.crt";
+} //Anonymous name space
+
+namespace ValidationCore {
+CertificatePtr RevocationCheckerBase::loadPEMFile(const char* fileName)
+{
+ DPL::ScopedFClose fd(fopen(fileName, "rb"));
+
+ // no such file, return NULL
+ if (!fd.Get()) {
+ return CertificatePtr();
+ }
+
+ // create a new X509 certificate basing on file
+ CertificatePtr cert(new Certificate(PEM_read_X509(fd.Get(),
+ NULL,
+ NULL,
+ NULL)));
+ return cert;
+}
+
+bool RevocationCheckerBase::sortCertList(CertificateList &lCertificates)
+{
+ CertificateCollection collection;
+ collection.load(lCertificates);
+
+ if (collection.sort()) {
+ lCertificates = collection.getChain();
+ return true;
+ }
+ return false;
+}
+
+} // ValidationCore
--- /dev/null
+/*
+ * 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.
+ */
+/*!
+ * @author Piotr Marcinkiewicz(p.marcinkiew@samsung.com)
+ * @version 0.4
+ * @file CommonCertValidator.h
+ * @brief Common routines for certificate validation over OCSP and CRL
+ */
+
+#ifndef WRT_ENGINE_SRC_VALIDATION_CORE_REVOCATIONCHECKERBASE_H_
+#define WRT_ENGINE_SRC_VALIDATION_CORE_REVOCATIONCHECKERBASE_H_
+
+#include <string>
+
+#include "Certificate.h"
+
+namespace ValidationCore {
+class RevocationCheckerBase
+{
+ public:
+ //! Loads a PEM file and returns X509 certificate object.
+ static CertificatePtr loadPEMFile(const char* path);
+
+ //! Sorts a list of certficates and verifies them if they form
+ //! a valid chain
+ static bool sortCertList(CertificateList &cert) __attribute__((deprecated));
+};
+} // ValidationCore
+
+#endif //ifndef WRT_ENGINE_SRC_VALIDATION_CORE_REVOCATIONCHECKERBASE_H_
+
--- /dev/null
+/*
+ * 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.
+ */
+#ifndef _SSLCONTAINERS_H
+#define _SSLCONTAINERS_H
+
+#include <openssl/x509v3.h>
+#include <openssl/ocsp.h>
+
+/*
+ * default deleter functor with no overloaded operator()
+ */
+template <typename T>
+struct MySSLFree {};
+
+/*
+ * macro for defining custom deleters for openssl structs
+ * usage DECLARE_DELETER(OpenSSLType)
+ */
+#define DECLARE_DELETER(Type) template<> \
+ struct MySSLFree <Type> \
+ { \
+ void operator() (Type* p) \
+ { \
+ Type ## _free(p); \
+ } \
+ \
+ };
+
+/*
+ * declare custom deleter for X509 structs
+ */
+DECLARE_DELETER(X509)
+/*
+ * declare custom deleter for OCSP_REQUEST structs
+ */
+DECLARE_DELETER(OCSP_REQUEST)
+/*
+ * declare custom deleter for OCSP_RESPONSE structs
+ */
+DECLARE_DELETER(OCSP_RESPONSE)
+/*
+ * declare custom deleter for OCSP_CERTID structs
+ */
+DECLARE_DELETER(OCSP_CERTID)
+/*
+ * declare custom deleter for OCSP_BASICRESP structs
+ */
+DECLARE_DELETER(OCSP_BASICRESP)
+/*
+ * declare custom deleter for X509_STORE structs
+ */
+DECLARE_DELETER(X509_STORE)
+
+/*
+ * undef it, so anyone could use that macro name
+ */
+#undef DECLARE_DELETER
+
+/*
+ * OpenSSL smart container
+ * usage SSLSmartContainer <OpenSSLType> smartptr = ptrToOpenSSLType
+ * remember to add OpenSSLType to macro list few lines above
+ */
+template <typename T, typename deleter = MySSLFree<T> >
+class SSLSmartContainer
+{
+ public:
+ SSLSmartContainer() : m_pData(NULL)
+ {
+ }
+
+ /*
+ * explicit constructor, we don't want any auto casting
+ */
+ explicit SSLSmartContainer(T* pData)
+ {
+ m_pData = pData;
+ }
+
+ /*
+ * overloaded assignment operator
+ */
+ SSLSmartContainer & operator=(SSLSmartContainer& pContainer)
+ {
+ /*
+ * check if no assignment was done before
+ */
+ if (this != &pContainer) {
+ // if so, free internal data
+ deleter ssl_free;
+ ssl_free(m_pData);
+
+ // and assign new
+ m_pData = pContainer.m_pData;
+
+ pContainer.m_pData = NULL;
+ }
+
+ return *this;
+ }
+
+ SSLSmartContainer & operator=(T* pData)
+ {
+ /*
+ * check if no assignment was done before
+ */
+ if (m_pData != pData) {
+ // if so, free internal data
+ deleter ssl_free;
+ ssl_free(m_pData);
+
+ // and assign new
+ m_pData = pData;
+ }
+
+ return *this;
+ }
+
+ ~SSLSmartContainer()
+ {
+ deleter ssl_free;
+ ssl_free(m_pData);
+ }
+
+ /*
+ * overloaded operators for standardptr - like usage
+ */
+ SSLSmartContainer & operator*()
+ {
+ return *m_pData;
+ }
+ SSLSmartContainer* operator->()
+ {
+ return m_pData;
+ }
+
+ /*
+ * auto cast to T operator
+ */
+ operator T *() const { return m_pData;
+ }
+
+ /*
+ * detachs internal pointer from smart pointer
+ */
+ T* DetachPtr()
+ {
+ T* pData = m_pData;
+ m_pData = NULL;
+ return pData;
+ }
+
+ private:
+ /*
+ * blocked assignment from another types operator
+ */
+ template <typename S>
+ T & operator = (S& pContainer)
+ {
+ return *this;
+ }
+
+ /*
+ * internal data
+ */
+ T* m_pData;
+};
+
+#endif /* _SSLCONTAINERS_H */
+
--- /dev/null
+/*
+ * 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 SaxReader.cpp
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief Simple c++ interface for libxml2.
+ */
+#include <dpl/assert.h>
+#include <dpl/exception.h>
+#include <dpl/log/log.h>
+
+#include <vcore/SaxReader.h>
+
+namespace ValidationCore {
+SaxReader::SaxReader() :
+ m_reader(0)
+{
+}
+
+SaxReader::~SaxReader()
+{
+ if (m_reader) {
+ deinitialize();
+ }
+}
+
+void SaxReader::initialize(const std::string &filename,
+ bool defaultArgs,
+ ValidationType validate,
+ const std::string &schema)
+{
+ Assert(m_reader == 0 && "Double initialization of SaxReader");
+
+ LogDebug("SaxReader opening file: " << filename);
+
+ /*
+ * create a new xml text reader
+ */
+ m_reader = xmlNewTextReaderFilename(filename.c_str());
+
+ if (m_reader == NULL) {
+ /*
+ * no such file, return
+ */
+ LogWarning("Error during opening file " << filename);
+ Throw(Exception::FileOpeningError);
+ }
+ if (validate == VALIDATION_XMLSCHEME &&
+ xmlTextReaderSchemaValidate(m_reader, schema.c_str())) {
+ /*
+ * unable to turn on schema validation
+ */
+ LogError("Turn on Schema validation failed.");
+ ThrowMsg(Exception::ParserInternalError,
+ "Turn on Scheme validation failed!");
+ }
+ // Path to DTD schema is taken from xml file.
+ if (validate == VALIDATION_DTD &&
+ xmlTextReaderSetParserProp(m_reader, XML_PARSER_VALIDATE, 1)) {
+ /*
+ * unable to turn on DTD validation
+ */
+ LogError("Turn on DTD validation failed!");
+ ThrowMsg(Exception::ParserInternalError,
+ "Turn on DTD validation failed!");
+ }
+ if (defaultArgs &&
+ xmlTextReaderSetParserProp(m_reader, XML_PARSER_DEFAULTATTRS, 1)) {
+ /*
+ * unable to turn on default arguments
+ */
+ LogError("Turn on default arguments failed");
+ ThrowMsg(Exception::ParserInternalError,
+ "Turn on Default Arguments failed!");
+ }
+}
+
+void SaxReader::deinitialize()
+{
+ xmlFreeTextReader(m_reader);
+ m_reader = 0;
+}
+
+bool SaxReader::next()
+{
+ int res = xmlTextReaderRead(m_reader);
+
+ if (0 == xmlTextReaderIsValid(m_reader)) {
+ LogWarning("Throw exception file not valid!");
+ Throw(Exception::FileNotValid);
+ }
+
+ if (res == 1) {
+ return true;
+ }
+
+ if (res == 0) {
+ return false;
+ }
+ LogError("ParserInternalError");
+ Throw(Exception::ParserInternalError);
+}
+
+void SaxReader::next(const std::string &token)
+{
+ xmlTextReaderRead(m_reader);
+ if (0 == xmlTextReaderIsValid(m_reader)) {
+ /*
+ * invalid file
+ */
+ LogWarning("Throw exception file not valid!");
+ Throw(Exception::FileNotValid);
+ }
+
+ xmlChar *name = xmlTextReaderName(m_reader);
+
+ if (name == NULL) {
+ /*
+ * invalid file
+ */
+ LogWarning("File not Valid");
+ Throw(Exception::FileNotValid);
+ }
+
+ if (token == reinterpret_cast<const char*>(name)) {
+ xmlFree(name);
+ } else {
+ /*
+ * we encountered wrong token
+ */
+ xmlFree(name);
+ LogWarning("Wrong Token");
+ Throw(Exception::WrongToken);
+ }
+}
+
+bool SaxReader::isEmpty(void)
+{
+ int ret = xmlTextReaderIsEmptyElement(m_reader);
+ if (-1 == ret) {
+ LogError("Parser Internal Error");
+ Throw(Exception::ParserInternalErrorInEmptyQuery);
+ }
+ return ret;
+}
+
+std::string SaxReader::attribute(const std::string &token,
+ ThrowType throwStatus)
+{
+ std::string value;
+ xmlChar *attr = xmlTextReaderGetAttribute(m_reader, BAD_CAST(token.c_str()));
+ if ((NULL == attr) && (throwStatus == THROW_DISABLE)) {
+ /*
+ * return empty string
+ */
+ //TODO why not DPL::Optional?
+ return std::string();
+ }
+ if (NULL == attr) {
+ /*
+ * error during read attribute
+ */
+ LogError("Error in reading attribute.");
+ Throw(Exception::ParserInternalErrorInReadingAttribute);
+ }
+
+ /*
+ * cast it to val and return it
+ */
+ value = reinterpret_cast<const char *>(attr);
+ xmlFree(attr);
+ return value;
+}
+
+// KW std::string SaxReader::fullName(){
+// KW std::string value;
+// KW xmlChar *name = xmlTextReaderName(m_reader);
+// KW if(NULL == name) {
+// KW LogError("Error in reading name.");
+// KW Throw(Exception::ErrorReadingName);
+// KW }
+// KW value = reinterpret_cast<const char *>(name);
+// KW xmlFree(name);
+// KW return value;
+// KW }
+
+std::string SaxReader::name()
+{
+ std::string value;
+ xmlChar *name = xmlTextReaderName(m_reader);
+ if (NULL == name) {
+ LogError("Error in reading name.");
+ Throw(Exception::ErrorReadingName);
+ }
+ value = reinterpret_cast<const char *>(name);
+ xmlFree(name);
+ size_t pos = value.find_last_of(":");
+ if (pos != std::string::npos) {
+ value.erase(0, pos + 1);
+ }
+ return value;
+}
+
+std::string SaxReader::namespaceURI()
+{
+ std::string value;
+ xmlChar *name = xmlTextReaderNamespaceUri(m_reader);
+ if (NULL != name) {
+ value = reinterpret_cast<const char *>(name);
+ xmlFree(name);
+ }
+ return value;
+}
+
+std::string SaxReader::value()
+{
+ std::string value;
+ /*
+ * get value of node
+ */
+ xmlChar *text = xmlTextReaderValue(m_reader);
+ if (NULL == text) {
+ LogError("Error in reading value");
+ Throw(Exception::ErrorReadingValue);
+ }
+ value = reinterpret_cast<const char*>(text);
+ /*
+ * free text and return the val
+ */
+ xmlFree(text);
+ return value;
+}
+
+SaxReader::NodeType SaxReader::type()
+{
+ xmlReaderTypes type =
+ static_cast<xmlReaderTypes>(xmlTextReaderNodeType(m_reader));
+ switch (type) {
+ case XML_READER_TYPE_ELEMENT:
+ return NODE_BEGIN;
+ case XML_READER_TYPE_END_ELEMENT:
+ return NODE_END;
+ case XML_READER_TYPE_TEXT:
+ return NODE_TEXT;
+ case XML_READER_TYPE_NONE:
+ case XML_READER_TYPE_ATTRIBUTE:
+ case XML_READER_TYPE_CDATA:
+ case XML_READER_TYPE_ENTITY_REFERENCE:
+ case XML_READER_TYPE_ENTITY:
+ case XML_READER_TYPE_PROCESSING_INSTRUCTION:
+ case XML_READER_TYPE_COMMENT:
+ case XML_READER_TYPE_DOCUMENT:
+ case XML_READER_TYPE_DOCUMENT_TYPE:
+ case XML_READER_TYPE_DOCUMENT_FRAGMENT:
+ case XML_READER_TYPE_NOTATION:
+ case XML_READER_TYPE_WHITESPACE:
+ case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
+ case XML_READER_TYPE_END_ENTITY:
+ case XML_READER_TYPE_XML_DECLARATION:
+ default:
+ return NODE_UNSUPPORTED;
+ }
+}
+
+void SaxReader::dumpNode(std::string &buffer)
+{
+ /*
+ * size of buffer
+ */
+ int size;
+ /*
+ * pointer to buffer
+ */
+ xmlBufferPtr buff = xmlBufferCreate();
+
+ xmlNodePtr node = xmlTextReaderExpand(m_reader);
+
+ if (node == NULL) {
+ /*
+ * internal parser error
+ */
+ xmlBufferFree(buff);
+ LogError("Parser Internal Error");
+ Throw(Exception::ParserInternalError);
+ }
+
+ /*
+ * get a size and fill in a buffer
+ */
+ size = xmlNodeDump(buff, node->doc, node, 0, 0);
+ buffer.insert(0, reinterpret_cast<char*>(buff->content), size);
+ xmlBufferFree(buff);
+}
+} // namespace ValidationCore
--- /dev/null
+/*
+ * 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 SaxReader.h
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief Simple c++ interface for libxml2.
+ * Its used in wrt-installer only and should be removed
+ * from cert-svc.
+ */
+#ifndef _SAXREADER_H_
+#define _SAXREADER_H_
+
+#include <string>
+#include <libxml/xmlreader.h>
+#include <dpl/exception.h>
+
+namespace ValidationCore {
+class SaxReader
+{
+ public:
+ SaxReader();
+ ~SaxReader();
+
+ /*
+ * custom exceptions
+ */
+ class Exception
+ {
+ public:
+ DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
+ DECLARE_EXCEPTION_TYPE(Base, FileOpeningError)
+ DECLARE_EXCEPTION_TYPE(Base, FileNotValid)
+ DECLARE_EXCEPTION_TYPE(Base, ParserInternalError)
+ DECLARE_EXCEPTION_TYPE(Base, WrongToken)
+ DECLARE_EXCEPTION_TYPE(Base, ParserInternalErrorInReadingAttribute)
+ DECLARE_EXCEPTION_TYPE(Base, ParserInternalErrorInEmptyQuery)
+ DECLARE_EXCEPTION_TYPE(Base, ErrorReadingValue)
+ DECLARE_EXCEPTION_TYPE(Base, ErrorReadingName)
+ DECLARE_EXCEPTION_TYPE(Base, UnsupportedType)
+ };
+
+ enum NodeType
+ {
+ NODE_UNSUPPORTED,
+ NODE_BEGIN,
+ NODE_END,
+ NODE_TEXT
+ };
+
+ enum ThrowType
+ {
+ THROW_ENABLE = 0,
+ THROW_DISABLE
+ };
+
+ /*
+ * xml validation modes
+ */
+ enum ValidationType
+ {
+ VALIDATION_DISABLE,
+ VALIDATION_XMLSCHEME,
+ VALIDATION_DTD
+ };
+
+ /*
+ * initializes parser
+ */
+ void initialize(const std::string &filename,
+ bool defaultArgs = false,
+ ValidationType validation = VALIDATION_DISABLE,
+ const std::string &schema = std::string());
+ /*
+ * deinitializes parser
+ */
+ void deinitialize();
+
+ /**
+ * Move to next xml node.
+ */
+ bool next();
+
+ /**
+ * Move to next xml node. If next node name is differ from token the exception will
+ * be thrown.
+ */
+ void next(const std::string &token);
+
+ /**
+ * Check if xml tag is empty.
+ */
+ bool isEmpty(void);
+
+ /**
+ * Read attribute tag.
+ */
+ std::string attribute(const std::string &token,
+ ThrowType throwStatus = THROW_ENABLE);
+
+ /**
+ * Read xml tag name with namespace.
+ */
+ // KW std::string fullName();
+
+ /**
+ * Read xml tag name without namespace.
+ */
+ std::string name();
+
+ /**
+ * Read xml tag namespace URI
+ */
+ std::string namespaceURI();
+
+ /**
+ * Read xml tag value.
+ */
+ std::string value();
+
+ /**
+ * Return information about node type.
+ */
+ NodeType type();
+
+ /**
+ * Save all contonet of xml file which is between current tag and
+ * it's close tag into buffer.
+ */
+ void dumpNode(std::string &buffer);
+
+ private:
+ /*
+ * internal libxml text reader
+ */
+ xmlTextReaderPtr m_reader;
+};
+}
+
+#endif // _SAXREADER_H_
--- /dev/null
+/*
+ * 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 SignatureData.cpp
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief SignatureData is used to storage data parsed from digsig file.
+ */
+#ifndef _SIGNATUREDATA_H_
+#define _SIGNATUREDATA_H_
+
+#include <list>
+#include <set>
+#include <string>
+
+#include <dpl/log/log.h>
+#include <dpl/noncopyable.h>
+#include <dpl/string.h>
+
+#include <vcore/Certificate.h>
+#include <vcore/CertStoreType.h>
+
+namespace ValidationCore {
+
+typedef std::set<std::string> ReferenceSet;
+typedef std::list<std::string> ObjectList;
+
+class SignatureData
+{
+ public:
+
+ SignatureData() :
+ m_signatureNumber(-1),
+ m_certificateSorted(false)
+ {
+ }
+
+ SignatureData(std::string fileName, int fileNumber)
+ : m_signatureNumber(fileNumber)
+ , m_fileName(fileName)
+ , m_certificateSorted(false)
+ {}
+
+ virtual ~SignatureData()
+ {}
+
+ typedef std::list<std::string> IMEIList;
+ typedef std::list<std::string> MEIDList;
+
+ const ReferenceSet& getReferenceSet() const
+ {
+ return m_referenceSet;
+ }
+
+ void setReference(const ReferenceSet &referenceSet)
+ {
+ m_referenceSet = referenceSet;
+ }
+
+ CertificateList getCertList(void) const
+ {
+ return m_certList;
+ }
+
+ void setSortedCertificateList(const CertificateList &list)
+ {
+ m_certList = list;
+ m_certificateSorted = true;
+ }
+
+ bool isAuthorSignature(void) const
+ {
+ return m_signatureNumber == -1;
+ }
+
+ std::string getSignatureFileName(void) const
+ {
+ return m_fileName;
+ }
+
+ int getSignatureNumber() const
+ {
+ return m_signatureNumber;
+ }
+
+ std::string getRoleURI() const
+ {
+ return m_roleURI;
+ }
+
+ std::string getProfileURI() const
+ {
+ return m_profileURI;
+ }
+
+ bool containObjectReference(const std::string &ref) const
+ {
+ std::string rName = "#";
+ rName += ref;
+ return m_referenceSet.end() != m_referenceSet.find(rName);
+ }
+
+ ObjectList getObjectList() const
+ {
+ return m_objectList;
+ }
+
+ void setStorageType(const CertStoreId::Set &storeIdSet)
+ {
+ m_storeIdSet = storeIdSet;
+ }
+
+ const CertStoreId::Set& getStorageType(void) const
+ {
+ return m_storeIdSet;
+ }
+
+ const IMEIList& getIMEIList() const
+ {
+ return m_imeiList;
+ }
+
+ const MEIDList& getMEIDList() const
+ {
+ return m_meidList;
+ }
+
+ CertificatePtr getEndEntityCertificatePtr() const
+ {
+ if (m_certificateSorted) {
+ return m_certList.front();
+ }
+ return CertificatePtr();
+ }
+
+ CertificatePtr getRootCaCertificatePtr() const
+ {
+ if (m_certificateSorted) {
+ return m_certList.back();
+ }
+ return CertificatePtr();
+ }
+
+ friend class SignatureReader;
+ private:
+ ReferenceSet m_referenceSet;
+ CertificateList m_certList;
+
+ //TargetRestriction
+ IMEIList m_imeiList;
+ MEIDList m_meidList;
+
+ /*
+ * 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 m_signatureNumber;
+ std::string m_fileName;
+ std::string m_roleURI;
+ std::string m_profileURI;
+ std::string m_identifier;
+ ObjectList m_objectList;
+ CertStoreId::Set m_storeIdSet;
+ bool m_certificateSorted;
+};
+
+typedef std::set<SignatureData> SignatureDataSet;
+
+} // ValidationCore
+
+#endif
--- /dev/null
+/*
+ * 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 SignatureFinder.cpp
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief Search for author-signature.xml and signatureN.xml files.
+ */
+#include <vcore/SignatureFinder.h>
+
+#include <dirent.h>
+#include <errno.h>
+#include <istream>
+
+#include <pcrecpp.h>
+
+#include <dpl/log/log.h>
+
+namespace ValidationCore {
+static const char *SIGNATURE_AUTHOR = "author-signature.xml";
+static const char *REGEXP_DISTRIBUTOR_SIGNATURE =
+ "^(signature)([1-9][0-9]*)(\\.xml)";
+
+class SignatureFinder::Impl {
+ public:
+ Impl(const std::string& dir)
+ : m_dir(dir)
+ , m_signatureRegexp(REGEXP_DISTRIBUTOR_SIGNATURE)
+ {}
+
+ virtual ~Impl(){}
+
+ Result find(SignatureFileInfoSet &set);
+
+ private:
+ std::string m_dir;
+ pcrecpp::RE m_signatureRegexp;
+};
+
+SignatureFinder::Result SignatureFinder::Impl::find(SignatureFileInfoSet &set)
+{
+ DIR *dp;
+ struct dirent *dirp;
+
+ /*
+ * find a dir
+ */
+ if ((dp = opendir(m_dir.c_str())) == NULL) {
+ LogError("Error opening directory:" << m_dir);
+ return ERROR_OPENING_DIR;
+ }
+
+ for (errno = 0; (dirp = readdir(dp)) != NULL; errno = 0) {
+ /**
+ * check if it's author signature
+ */
+ if (!strcmp(dirp->d_name, SIGNATURE_AUTHOR)) {
+ set.insert(SignatureFileInfo(std::string(dirp->d_name), -1));
+ continue;
+ }
+
+ std::string sig, num, xml;
+ if (m_signatureRegexp.FullMatch(dirp->d_name, &sig, &num, &xml)) {
+ std::istringstream stream(num);
+ int number;
+ stream >> number;
+
+ if (stream.fail()) {
+ closedir(dp);
+ return ERROR_ISTREAM;
+ }
+
+ set.insert(SignatureFileInfo(std::string(dirp->d_name), number));
+ }
+ }
+
+ if (errno != 0) {
+ LogError("Error in readdir");
+ closedir(dp);
+ return ERROR_READING_DIR;
+ }
+
+ closedir(dp);
+ return NO_ERROR;
+}
+
+SignatureFinder::SignatureFinder(const std::string& dir)
+ : m_impl(new Impl(dir))
+{}
+
+SignatureFinder::~SignatureFinder(){
+ delete m_impl;
+}
+
+SignatureFinder::Result SignatureFinder::find(SignatureFileInfoSet &set) {
+ return m_impl->find(set);
+}
+
+} // namespace ValidationCore
--- /dev/null
+/*
+ * 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 SignatureFinder.h
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief Search for author-signature.xml and signatureN.xml files.
+ * This class is WAC 2.0 specific and shuld be moved to
+ * wrt-installer.
+ */
+#ifndef _VALIDATION_CORE_SIGNATUREFINDER_H_
+#define _VALIDATION_CORE_SIGNATUREFINDER_H_
+
+#include <set>
+#include <string>
+
+#include <dpl/noncopyable.h>
+
+namespace ValidationCore {
+class SignatureFileInfo
+{
+ public:
+ SignatureFileInfo(const std::string &fileName, int num)
+ : m_fileName(fileName)
+ , m_fileNumber(num)
+ {}
+
+ std::string getFileName() const
+ {
+ return m_fileName;
+ }
+
+ int getFileNumber() const
+ {
+ return m_fileNumber;
+ }
+
+ bool operator<(const SignatureFileInfo &second) const
+ {
+ return m_fileNumber < second.m_fileNumber;
+ }
+ private:
+ std::string m_fileName;
+ int m_fileNumber;
+};
+
+typedef std::set<SignatureFileInfo> SignatureFileInfoSet;
+
+class SignatureFinder : DPL::Noncopyable {
+ public:
+ enum Result
+ {
+ NO_ERROR,
+ ERROR_OPENING_DIR,
+ ERROR_READING_DIR,
+ ERROR_ISTREAM
+ };
+
+ SignatureFinder(const std::string& dir);
+
+ virtual ~SignatureFinder();
+
+ Result find(SignatureFileInfoSet &set);
+
+ private:
+ class Impl;
+ Impl *m_impl;
+};
+
+} // namespace ValidationCore
+
+#endif // _VALIDATION_CORE_SIGNATUREFINDER_H_
--- /dev/null
+/*
+ * 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 SignatureReader.cpp
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief SignatureReader is used to parse widget digital signature.
+ */
+#include <vcore/SignatureReader.h>
+
+#include <vcore/CertificateLoader.h>
+
+namespace ValidationCore {
+static const std::string XML_NAMESPACE =
+ "http://www.w3.org/2000/09/xmldsig#";
+static const std::string XML_NAMESPACE_DIGITALSIG =
+ "http://wacapps.net/ns/digsig";
+static const std::string XML_OBJ_NS =
+ "http://www.w3.org/2009/xmldsig-properties";
+
+// TAG TOKENS
+static const std::string TOKEN_SIGNATURE = "Signature";
+static const std::string TOKEN_SIGNED_INFO = "SignedInfo";
+static const std::string TOKEN_CANONICALIZATION_METHOD =
+ "CanonicalizationMethod";
+static const std::string TOKEN_SIGNATURE_METHOD = "SignatureMethod";
+static const std::string TOKEN_REFERENCE = "Reference";
+static const std::string TOKEN_TRANSFORMS = "Transforms";
+static const std::string TOKEN_TRANSFORM = "Transform";
+static const std::string TOKEN_DIGEST_METHOD = "DigestMethod";
+static const std::string TOKEN_DIGEST_VALUE = "DigestValue";
+static const std::string TOKEN_SIGNATURE_VALUE = "SignatureValue";
+static const std::string TOKEN_KEY_INFO = "KeyInfo";
+static const std::string TOKEN_X509DATA = "X509Data";
+static const std::string TOKEN_X509CERTIFICATE = "X509Certificate";
+static const std::string TOKEN_KEY_VALUE = "KeyValue";
+static const std::string TOKEN_RSA_KEY_VALUE = "RSAKeyValue";
+static const std::string TOKEN_MODULUS_COMPONENT = "Modulus";
+static const std::string TOKEN_EXPONENT_COMPONENT = "Exponent";
+static const std::string TOKEN_ECKEY_VALUE = "ECKeyValue";
+static const std::string TOKEN_NAMED_CURVE = "NamedCurve";
+static const std::string TOKEN_PUBLIC_KEY = "PublicKey";
+static const std::string TOKEN_OBJECT = "Object";
+static const std::string TOKEN_SIGNATURE_PROPERTIES = "SignatureProperties";
+static const std::string TOKEN_SIGNATURE_PROPERTY = "SignatureProperty";
+static const std::string TOKEN_PROFILE = "Profile";
+static const std::string TOKEN_ROLE = "Role";
+static const std::string TOKEN_IDENTIFIER = "Identifier";
+static const std::string TOKEN_DSAKEYVALUE = "DSAKeyValue";
+static const std::string TOKEN_DSA_P_COMPONENT = "P";
+static const std::string TOKEN_DSA_Q_COMPONENT = "Q";
+static const std::string TOKEN_DSA_G_COMPONENT = "G";
+static const std::string TOKEN_DSA_Y_COMPONENT = "Y";
+static const std::string TOKEN_DSA_J_COMPONENT = "J";
+static const std::string TOKEN_DSA_SEED_COMPONENT = "Seed";
+static const std::string TOKEN_DSA_PGENCOUNTER_COMPONENT = "PgenCounter";
+static const std::string TOKEN_TARGET_RESTRICTION = "TargetRestriction";
+
+// ATTRIBUTTE TOKENS
+
+static const std::string TOKEN_ALGORITHM = "Algorithm";
+static const std::string TOKEN_URI = "URI";
+static const std::string TOKEN_ID = "Id";
+static const std::string TOKEN_TARGET = "Target";
+static const std::string TOKEN_IMEI = "IMEI";
+static const std::string TOKEN_MEID = "MEID";
+
+// ATTIRUBTE VALUES
+
+static const std::string TOKEN_ATTR_PROFILE = "profile";
+static const std::string TOKEN_ATTR_ROLE = "role";
+static const std::string TOKEN_ATTR_IDENTIFIER = "identifier";
+
+// ALGORITHMS
+
+//static const std::string TOKEN_ALGORITHM_XML_EXC_CAN =
+// "http://www.w3.org/2001/10/xml-exc-c14n#";
+//static const std::string TOKEN_ALGORITHM_RSA_SHA256 =
+// "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
+//static const std::string TOKEN_ALGORITHM_DSA_SHA1 =
+// "http://www.w3.org/2000/09/xmldsig#dsa-sha1";
+//static const std::string TOKEN_ALGORITHM_ECDSA_SHA256 =
+// "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256";
+//static const std::string TOKEN_ALGORITHM_SHA1 =
+// "http://www.w3.org/2000/09/xmldsig#sha1";
+//static const std::string TOKEN_ALGORITHM_SHA256 =
+// "http://www.w3.org/2001/04/xmlenc#sha256";
+//static const std::string TOKEN_ALGORITHM_SHA384 =
+// "http://www.w3.org/2001/04/xmldsig-more#sha384";
+//static const std::string TOKEN_ALGORITHM_SHA512 =
+// "http://www.w3.org/2001/04/xmlenc#sha512";
+
+SignatureReader::SignatureReader() :
+ m_signaturePropertiesCounter(0),
+ m_targetRestrictionObjectFound(false),
+ m_parserSchema(this)
+{
+ /**
+ * member func pointers map
+ */
+ m_parserSchema.addBeginTagCallback(TOKEN_SIGNATURE,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_SIGNED_INFO,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_CANONICALIZATION_METHOD,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_SIGNATURE_METHOD,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_REFERENCE,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_TRANSFORMS,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_TRANSFORM,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_DIGEST_METHOD,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_DIGEST_VALUE,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_SIGNATURE_VALUE,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_KEY_INFO,
+ XML_NAMESPACE,
+ &SignatureReader::tokenKeyInfo);
+ m_parserSchema.addBeginTagCallback(TOKEN_X509DATA,
+ XML_NAMESPACE,
+ &SignatureReader::tokenX509Data);
+ m_parserSchema.addBeginTagCallback(TOKEN_X509CERTIFICATE,
+ XML_NAMESPACE,
+ &SignatureReader::tokenX509Certificate);
+ m_parserSchema.addBeginTagCallback(TOKEN_ECKEY_VALUE,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_NAMED_CURVE,
+ XML_NAMESPACE,
+ &SignatureReader::tokenNamedCurve);
+ m_parserSchema.addBeginTagCallback(TOKEN_PUBLIC_KEY,
+ XML_NAMESPACE,
+ &SignatureReader::tokenPublicKey);
+ m_parserSchema.addBeginTagCallback(TOKEN_OBJECT,
+ XML_NAMESPACE,
+ &SignatureReader::tokenObject);
+ m_parserSchema.addBeginTagCallback(
+ TOKEN_SIGNATURE_PROPERTIES,
+ XML_NAMESPACE,
+ &SignatureReader::
+ tokenSignatureProperties);
+ m_parserSchema.addBeginTagCallback(TOKEN_SIGNATURE_PROPERTY,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_PROFILE,
+ XML_OBJ_NS,
+ &SignatureReader::tokenProfile);
+ m_parserSchema.addBeginTagCallback(TOKEN_ROLE,
+ XML_OBJ_NS,
+ &SignatureReader::tokenRole);
+ m_parserSchema.addBeginTagCallback(TOKEN_IDENTIFIER,
+ XML_OBJ_NS,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_KEY_VALUE,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_DSAKEYVALUE,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_DSA_P_COMPONENT,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_DSA_Q_COMPONENT,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_DSA_G_COMPONENT,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_DSA_Y_COMPONENT,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_DSA_J_COMPONENT,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_DSA_SEED_COMPONENT,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_DSA_PGENCOUNTER_COMPONENT,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_RSA_KEY_VALUE,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_MODULUS_COMPONENT,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_EXPONENT_COMPONENT,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addBeginTagCallback(TOKEN_TARGET_RESTRICTION,
+ XML_NAMESPACE_DIGITALSIG,
+ &SignatureReader::tokenTargetRestriction);
+
+ m_parserSchema.addEndTagCallback(TOKEN_SIGNATURE,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addEndTagCallback(TOKEN_SIGNED_INFO,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addEndTagCallback(TOKEN_CANONICALIZATION_METHOD,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addEndTagCallback(TOKEN_SIGNATURE_METHOD,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addEndTagCallback(TOKEN_REFERENCE,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addEndTagCallback(TOKEN_TRANSFORMS,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addEndTagCallback(TOKEN_TRANSFORM,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addEndTagCallback(TOKEN_DIGEST_METHOD,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addEndTagCallback(TOKEN_DIGEST_VALUE,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addEndTagCallback(TOKEN_SIGNATURE_VALUE,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addEndTagCallback(TOKEN_KEY_INFO,
+ XML_NAMESPACE,
+ &SignatureReader::tokenEndKeyInfo);
+ m_parserSchema.addEndTagCallback(TOKEN_X509DATA,
+ XML_NAMESPACE,
+ &SignatureReader::tokenEndX509Data);
+ m_parserSchema.addEndTagCallback(TOKEN_X509CERTIFICATE,
+ XML_NAMESPACE,
+ &SignatureReader::tokenEndX509Certificate);
+ m_parserSchema.addEndTagCallback(TOKEN_ECKEY_VALUE,
+ XML_NAMESPACE,
+ &SignatureReader::tokenEndECKeyValue);
+ m_parserSchema.addEndTagCallback(TOKEN_PUBLIC_KEY,
+ XML_NAMESPACE,
+ &SignatureReader::tokenEndPublicKey);
+ m_parserSchema.addEndTagCallback(TOKEN_OBJECT,
+ XML_NAMESPACE,
+ &SignatureReader::tokenEndObject);
+ m_parserSchema.addEndTagCallback(TOKEN_SIGNATURE_PROPERTIES,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addEndTagCallback(TOKEN_SIGNATURE_PROPERTY,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addEndTagCallback(TOKEN_PROFILE,
+ XML_OBJ_NS,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addEndTagCallback(TOKEN_ROLE,
+ XML_OBJ_NS,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addEndTagCallback(TOKEN_IDENTIFIER,
+ XML_OBJ_NS,
+ &SignatureReader::tokenEndIdentifier);
+ m_parserSchema.addEndTagCallback(TOKEN_KEY_VALUE,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+ m_parserSchema.addEndTagCallback(TOKEN_DSAKEYVALUE,
+ XML_NAMESPACE,
+ &SignatureReader::tokenEndDSAKeyValue);
+ m_parserSchema.addEndTagCallback(TOKEN_DSA_P_COMPONENT,
+ XML_NAMESPACE,
+ &SignatureReader::tokenEndDSAPComponent);
+ m_parserSchema.addEndTagCallback(TOKEN_DSA_Q_COMPONENT,
+ XML_NAMESPACE,
+ &SignatureReader::tokenEndDSAQComponent);
+ m_parserSchema.addEndTagCallback(TOKEN_DSA_G_COMPONENT,
+ XML_NAMESPACE,
+ &SignatureReader::tokenEndDSAGComponent);
+ m_parserSchema.addEndTagCallback(TOKEN_DSA_Y_COMPONENT,
+ XML_NAMESPACE,
+ &SignatureReader::tokenEndDSAYComponent);
+ m_parserSchema.addEndTagCallback(TOKEN_DSA_J_COMPONENT,
+ XML_NAMESPACE,
+ &SignatureReader::tokenEndDSAJComponent);
+ m_parserSchema.addEndTagCallback(TOKEN_DSA_SEED_COMPONENT,
+ XML_NAMESPACE,
+ &SignatureReader::tokenEndDSASeedComponent);
+ m_parserSchema.addEndTagCallback(
+ TOKEN_DSA_PGENCOUNTER_COMPONENT,
+ XML_NAMESPACE,
+ &SignatureReader::
+ tokenEndDSAPGenCounterComponent);
+ m_parserSchema.addEndTagCallback(TOKEN_RSA_KEY_VALUE,
+ XML_NAMESPACE,
+ &SignatureReader::tokenEndRSAKeyValue);
+ m_parserSchema.addEndTagCallback(TOKEN_MODULUS_COMPONENT,
+ XML_NAMESPACE,
+ &SignatureReader::tokenEndKeyModulus);
+ m_parserSchema.addEndTagCallback(TOKEN_EXPONENT_COMPONENT,
+ XML_NAMESPACE,
+ &SignatureReader::tokenEndKeyExponent);
+ m_parserSchema.addEndTagCallback(TOKEN_TARGET_RESTRICTION,
+ XML_NAMESPACE,
+ &SignatureReader::blankFunction);
+}
+
+void SignatureReader::tokenKeyInfo(SignatureData &signatureData)
+{
+ (void)signatureData;
+}
+void SignatureReader::tokenX509Data(SignatureData &signatureData)
+{
+ (void)signatureData;
+}
+void SignatureReader::tokenX509Certificate(SignatureData &signatureData)
+{
+ (void)signatureData;
+}
+void SignatureReader::tokenPublicKey(SignatureData &signatureData)
+{
+ (void)signatureData;
+}
+
+void SignatureReader::tokenNamedCurve(SignatureData &signatureData)
+{
+ (void)signatureData;
+ m_nameCurveURI = m_parserSchema.getReader().attribute(TOKEN_URI);
+}
+
+void SignatureReader::tokenTargetRestriction(SignatureData &signatureData)
+{
+ std::string IMEI = m_parserSchema.getReader().attribute(
+ TOKEN_IMEI,
+ SaxReader::
+ THROW_DISABLE);
+ std::string MEID = m_parserSchema.getReader().attribute(
+ TOKEN_MEID,
+ SaxReader::
+ THROW_DISABLE);
+
+ //less verbose way to say (IMEI && MEID) || (!IMEI && !MEID)
+ if (IMEI.empty() == MEID.empty()) {
+ //WAC 2.0 WR-4650 point 4
+ ThrowMsg(Exception::TargetRestrictionException,
+ "TargetRestriction should contain exactly one attribute.");
+ return;
+ }
+
+ if (!IMEI.empty()) {
+ signatureData.m_imeiList.push_back(IMEI);
+ }
+ if (!MEID.empty()) {
+ signatureData.m_meidList.push_back(MEID);
+ }
+}
+
+void SignatureReader::tokenEndKeyInfo(SignatureData &signatureData)
+{
+ (void)signatureData;
+}
+
+void SignatureReader::tokenEndX509Data(SignatureData &signatureData)
+{
+ (void)signatureData;
+}
+
+void SignatureReader::tokenEndX509Certificate(SignatureData &signatureData)
+{
+ CertificateLoader loader;
+ if (CertificateLoader::NO_ERROR !=
+ loader.loadCertificateFromRawData(m_parserSchema.getText())) {
+ LogWarning("Certificate could not be loaded!");
+ ThrowMsg(ParserSchemaException::CertificateLoaderError,
+ "Certificate could not be loaded.");
+ }
+ signatureData.m_certList.push_back(loader.getCertificatePtr());
+}
+// KW void SignatureReader::tokenEndKeyName(SignatureData &signatureData){
+// KW CertificateLoader loader;
+// KW if(CertificateLoader::NO_ERROR != loader.loadCertificateBasedOnSubjectName(m_parserSchema.getText())){
+// KW LogError("Certificate could not be loaded!");
+// KW ThrowMsg(ParserSchemaException::CertificateLoaderError, "Certificate could not be loaded.");
+// KW }
+// KW signatureData.m_certList.push_back(loader);
+// KW }
+
+void SignatureReader::tokenEndRSAKeyValue(SignatureData &signatureData)
+{
+ CertificateLoader loader;
+ if (CertificateLoader::NO_ERROR !=
+ loader.loadCertificateBasedOnExponentAndModulus(m_modulus,
+ m_exponent)) {
+ LogWarning("Certificate could not be loaded!");
+ ThrowMsg(ParserSchemaException::CertificateLoaderError,
+ "Certificate could not be loaded.");
+ }
+ signatureData.m_certList.push_back(loader.getCertificatePtr());
+}
+
+void SignatureReader::tokenEndKeyModulus(SignatureData &signatureData)
+{
+ (void)signatureData;
+ m_modulus = m_parserSchema.getText();
+}
+
+void SignatureReader::tokenEndKeyExponent(SignatureData &signatureData)
+{
+ (void)signatureData;
+ m_exponent = m_parserSchema.getText();
+}
+
+void SignatureReader::tokenEndPublicKey(SignatureData &signatureData)
+{
+ (void)signatureData;
+ m_publicKey = m_parserSchema.getText();
+}
+
+void SignatureReader::tokenEndECKeyValue(SignatureData &signatureData)
+{
+ CertificateLoader loader;
+ if (CertificateLoader::NO_ERROR !=
+ loader.loadCertificateWithECKEY(m_nameCurveURI, m_publicKey)) {
+ ThrowMsg(ParserSchemaException::CertificateLoaderError,
+ "Certificate could not be loaded.");
+ }
+ signatureData.m_certList.push_back(loader.getCertificatePtr());
+}
+
+void SignatureReader::tokenEndObject(SignatureData &signatureData)
+{
+ m_signaturePropertiesCounter = 0;
+
+ if (((!signatureData.m_imeiList.empty()) ||
+ (!signatureData.m_meidList.empty())) &&
+ m_targetRestrictionObjectFound) {
+ //WAC 2.0 WR-4650 point 1
+ ThrowMsg(
+ Exception::TargetRestrictionException,
+ "TargetRestriction should contain exactly one ds:Object containing zero or more wac:TargetRestriction children.");
+ return;
+ }
+ if ((!signatureData.m_imeiList.empty()) ||
+ (!signatureData.m_meidList.empty())) {
+ m_targetRestrictionObjectFound = true;
+ }
+}
+void SignatureReader::tokenEndDSAPComponent(SignatureData& signatureData)
+{
+ (void)signatureData;
+ m_dsaKeyPComponent = m_parserSchema.getText();
+}
+
+void SignatureReader::tokenEndDSAQComponent(SignatureData& signatureData)
+{
+ (void)signatureData;
+ m_dsaKeyQComponent = m_parserSchema.getText();
+}
+
+void SignatureReader::tokenEndDSAGComponent(SignatureData& signatureData)
+{
+ (void)signatureData;
+ m_dsaKeyGComponent = m_parserSchema.getText();
+}
+
+void SignatureReader::tokenEndDSAYComponent(SignatureData& signatureData)
+{
+ (void)signatureData;
+ m_dsaKeyYComponent = m_parserSchema.getText();
+}
+
+void SignatureReader::tokenEndDSAJComponent(SignatureData& signatureData)
+{
+ (void)signatureData;
+ m_dsaKeyJComponent = m_parserSchema.getText();
+}
+
+void SignatureReader::tokenEndDSASeedComponent(SignatureData& signatureData)
+{
+ (void)signatureData;
+ m_dsaKeySeedComponent = m_parserSchema.getText();
+}
+
+void SignatureReader::tokenEndDSAPGenCounterComponent(
+ SignatureData& signatureData)
+{
+ (void)signatureData;
+ m_dsaKeyPGenCounter = m_parserSchema.getText();
+}
+
+void SignatureReader::tokenEndDSAKeyValue(SignatureData& signatureData)
+{
+ CertificateLoader loader;
+
+ if (CertificateLoader::NO_ERROR !=
+ loader.loadCertificateBasedOnDSAComponents(m_dsaKeyPComponent,
+ m_dsaKeyQComponent,
+ m_dsaKeyGComponent,
+ m_dsaKeyYComponent,
+ m_dsaKeyJComponent,
+ m_dsaKeySeedComponent,
+ m_dsaKeyPGenCounter)) {
+ LogWarning("Certificate could not be loaded.");
+ ThrowMsg(ParserSchemaException::CertificateLoaderError,
+ "Certificate could not be loaded.");
+ }
+ signatureData.m_certList.push_back(loader.getCertificatePtr());
+}
+
+void SignatureReader::tokenRole(SignatureData &signatureData)
+{
+ if (!signatureData.m_roleURI.empty()) {
+ LogWarning("Multiple definition of Role is not allowed.");
+ ThrowMsg(ParserSchemaException::UnsupportedValue,
+ "Multiple definition of Role is not allowed.");
+ }
+ signatureData.m_roleURI = m_parserSchema.getReader().attribute(TOKEN_URI);
+}
+
+void SignatureReader::tokenProfile(SignatureData &signatureData)
+{
+ if (!signatureData.m_profileURI.empty()) {
+ LogWarning("Multiple definition of Profile is not allowed.");
+ ThrowMsg(ParserSchemaException::UnsupportedValue,
+ "Multiple definition of Profile is not allowed.");
+ }
+ signatureData.m_profileURI = m_parserSchema.getReader().attribute(TOKEN_URI);
+}
+
+void SignatureReader::tokenEndIdentifier(SignatureData &signatureData)
+{
+ if (!signatureData.m_identifier.empty()) {
+ LogWarning("Multiple definition of Identifier is not allowed.");
+ ThrowMsg(ParserSchemaException::UnsupportedValue,
+ "Multiple definition of Identifier is not allowed.");
+ }
+ signatureData.m_identifier = m_parserSchema.getText();
+}
+
+void SignatureReader::tokenObject(SignatureData &signatureData)
+{
+ std::string id = m_parserSchema.getReader().attribute(TOKEN_ID);
+
+ if (id.empty()) {
+ LogWarning("Unsupported value of Attribute Id in Object tag.");
+ ThrowMsg(ParserSchemaException::UnsupportedValue,
+ "Unsupported value of Attribute Id in Object tag.");
+ }
+
+ signatureData.m_objectList.push_back(id);
+}
+
+void SignatureReader::tokenSignatureProperties(SignatureData &signatureData)
+{
+ (void)signatureData;
+ if (++m_signaturePropertiesCounter > 1) {
+ LogWarning("Only one SignatureProperties tag is allowed in Object");
+ ThrowMsg(ParserSchemaException::UnsupportedValue,
+ "Only one SignatureProperties tag is allowed in Object");
+ }
+}
+} // namespace ValidationCore
--- /dev/null
+/*
+ * 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 SignatureReader.h
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief SignatureReader is used to parse widget digital signature.
+ */
+#ifndef _VALIDATION_CORE_SIGNATUREREADER_H_
+#define _VALIDATION_CORE_SIGNATUREREADER_H_
+
+#include <map>
+#include <dpl/log/log.h>
+
+#include <vcore/SignatureData.h>
+#include <vcore/ParserSchema.h>
+
+namespace ValidationCore {
+class SignatureReader
+{
+ public:
+ class Exception
+ {
+ public:
+ DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
+ DECLARE_EXCEPTION_TYPE(Base, TargetRestrictionException)
+ };
+
+ SignatureReader();
+
+ void initialize(SignatureData &data,
+ const std::string &xmlscheme)
+ {
+ m_parserSchema.initialize(
+ data.getSignatureFileName(), true, SaxReader::VALIDATION_XMLSCHEME,
+ xmlscheme);
+ }
+
+ void read(SignatureData &data)
+ {
+ m_parserSchema.read(data);
+ }
+
+ private:
+ void blankFunction(SignatureData &)
+ {
+ }
+
+ void tokenKeyInfo(SignatureData &signatureData);
+ void tokenKeyModulus(SignatureData &signatureData);
+ void tokenKeyExponent(SignatureData &signatureData);
+ void tokenX509Data(SignatureData &signatureData);
+ void tokenX509Certificate(SignatureData &signatureData);
+ void tokenPublicKey(SignatureData &signatureData);
+ void tokenNamedCurve(SignatureData &signatureData);
+ void tokenRole(SignatureData &signatureData);
+ void tokenProfile(SignatureData &signatureData);
+ void tokenObject(SignatureData &signatureData);
+ void tokenSignatureProperties(SignatureData &signatureData);
+ void tokenTargetRestriction(SignatureData &signatureData);
+
+ void tokenEndKeyInfo(SignatureData &signatureData);
+ // KW void tokenEndKeyName(SignatureData &signatureData);
+ void tokenEndRSAKeyValue(SignatureData &signatureData);
+ void tokenEndKeyModulus(SignatureData &signatureData);
+ void tokenEndKeyExponent(SignatureData &signatureData);
+ void tokenEndX509Data(SignatureData &signatureData);
+ void tokenEndX509Certificate(SignatureData &signatureData);
+ void tokenEndPublicKey(SignatureData &signatureData);
+ void tokenEndECKeyValue(SignatureData &signatureData);
+ void tokenEndIdentifier(SignatureData &signatureData);
+ void tokenEndObject(SignatureData &signatureData);
+
+ // DSA key components
+ void tokenEndDSAPComponent(SignatureData& signatureData);
+ void tokenEndDSAQComponent(SignatureData& signatureData);
+ void tokenEndDSAGComponent(SignatureData& signatureData);
+ void tokenEndDSAYComponent(SignatureData& signatureData);
+ void tokenEndDSAJComponent(SignatureData& signatureData);
+
+ void tokenEndDSAKeyValue(SignatureData& signatureData);
+
+ void tokenEndDSASeedComponent(SignatureData& signatureData);
+ void tokenEndDSAPGenCounterComponent(SignatureData& signatureData);
+
+ // temporary values required due reference parsing process
+ // optional parameters for dsa
+ std::string m_dsaKeyPComponent;
+ std::string m_dsaKeyQComponent;
+ std::string m_dsaKeyGComponent;
+ std::string m_dsaKeyYComponent;
+ std::string m_dsaKeyJComponent;
+ std::string m_dsaKeySeedComponent;
+ std::string m_dsaKeyPGenCounter;
+ // temporary values of ecdsa key
+ std::string m_publicKey;
+ std::string m_nameCurveURI;
+ std::string m_modulus;
+ std::string m_exponent;
+
+ // temporary values required due Object parsing
+ int m_signaturePropertiesCounter;
+ bool m_targetRestrictionObjectFound;
+
+ ParserSchema<SignatureReader, SignatureData> m_parserSchema;
+};
+}
+
+#endif // _VALIDATION_CORE_SIGNATUREREADER_H_
--- /dev/null
+/*
+ * 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.
+ */
--- /dev/null
+/*
+ * 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.
+ */
+/*!
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 0.1
+ * @file SoupMessageSendAsync.h
+ * @brief Routines for certificate validation over OCSP
+ */
+#ifndef _SRC_VALIDATION_CORE_SOUP_MESSAGE_SEND_ASYNC_H_
+#define _SRC_VALIDATION_CORE_SOUP_MESSAGE_SEND_ASYNC_H_
+
+#include <map>
+#include <vector>
+
+#include <dpl/assert.h>
+
+#include <dpl/event/inter_context_delegate.h>
+
+#include <vcore/SoupMessageSendBase.h>
+
+namespace SoupWrapper {
+
+class SoupMessageSendAsync
+ : public SoupMessageSendBase
+ , public DPL::Event::ICDelegateSupport<SoupMessageSendAsync>
+{
+ typedef DPL::Event::ICDelegate<SoupSession*, SoupMessage*, void*> SoupDelegate;
+ public:
+ void sendAsync() {
+ Assert(m_status == STATUS_IDLE);
+ Assert(!m_soupSession);
+ Assert(!m_soupMessage);
+
+ m_status = STATUS_SEND_ASYNC;
+ m_tryLeft = m_tryCount;
+ m_mainContext = g_main_context_new();
+
+ if (!m_mainContext){
+ m_status = STATUS_IDLE;
+
+ // call the delegate to outside with error!
+ return;
+ }
+
+ m_soupSession = soup_session_async_new_with_options(
+ SOUP_SESSION_ASYNC_CONTEXT,
+ m_mainContext,
+ SOUP_SESSION_TIMEOUT,
+ m_timeout,
+ NULL);
+
+ if (!m_soupSession){
+ m_status = STATUS_IDLE;
+ g_object_unref(m_mainContext);
+ m_mainContext = 0;
+
+ // call the deletage to outside with error!
+ return;
+ }
+
+ m_soupMessage = createRequest();
+
+ if (!m_soupMessage){
+ m_status = STATUS_IDLE;
+ g_object_unref(m_soupSession);
+ m_soupSession = 0;
+ g_object_unref(m_mainContext);
+ m_mainContext = 0;
+
+ // call the delegate to outsize with error!
+ return;
+ }
+
+ sendAsyncIterationStart();
+ }
+
+ protected:
+
+ struct SoupDelegateOpaque {
+ SoupDelegate dlg;
+ };
+
+ void sendAsyncIterationStart(){
+ // ICDelegate could be called only once.
+ // We can set user data only once.
+ // We need nasty hack because we will call ICDelegate m_tryCount times.
+ SoupDelegateOpaque *opaq = new SoupDelegateOpaque;
+ opaq->dlg = makeICDelegate(&SoupMessageSendAsync::requestReceiver);
+
+ soup_session_queue_message(m_soupSession,
+ m_soupMessage,
+ soupSessionCallback,
+ reinterpret_cast<gpointer>(opaq));
+ }
+
+ void sendAsyncIteration(SoupDelegateOpaque *opaq){
+ // Replace used ICDelegate with new one without changing
+ // userdata ;-)
+ opaq->dlg = makeICDelegate(&SoupMessageSendAsync::requestReceiver);
+ soup_session_requeue_message(m_soupSession,
+ m_soupMessage);
+ }
+
+ void requestReceiver(SoupSession *session, SoupMessage *msg, void *opaque){
+ // We are in thread which called sendAsync function.
+ Assert(session == m_soupSession);
+ Assert(msg == m_soupMessage);
+ Assert(opaque != 0);
+ Assert(m_status == STATUS_SEND_ASYNC);
+
+ m_tryLeft--;
+
+ if (msg->status_code == SOUP_STATUS_OK) {
+ m_responseBuffer.resize(msg->response_body->length);
+ memcpy(&m_responseBuffer[0],
+ msg->response_body->data,
+ msg->response_body->length);
+ // We are done.
+ m_status = STATUS_IDLE;
+ delete static_cast<SoupDelegateOpaque*>(opaque);
+
+ // call the delegate to outside!
+ return;
+ }
+
+ // Error protocol //
+ if (m_tryLeft <= 0) {
+ m_status = STATUS_IDLE;
+ delete static_cast<SoupDelegateOpaque*>(opaque);
+
+ // call the delegate to outside with error!
+ return;
+ }
+
+ // create delegate and send the request once again.
+ sendAsyncIteration(reinterpret_cast<SoupDelegateOpaque*>(opaque));
+ }
+
+ static void soupSessionCallback(SoupSession *session,
+ SoupMessage *msg,
+ gpointer userdata)
+ {
+ // We are in main thread. We need to switch context.
+ // This delegate can switch context to dpl thread or main thread.
+ SoupDelegateOpaque *opaque;
+ opaque = reinterpret_cast<SoupDelegateOpaque*>(userdata);
+ opaque->dlg(session, msg, userdata);
+ }
+
+ int m_tryLeft;
+
+ GMainContext *m_mainContext;
+ SoupSession *m_soupSession;
+ SoupMessage *m_soupMessage;
+};
+
+} // namespace ValidationCore
+
+#endif
--- /dev/null
+/*
+ * 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.
+ */
+/*!
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 0.1
+ * @file SoupMessageSendBase.cpp
+ * @brief Simple wrapper for soup.
+ */
+#include <vcore/SoupMessageSendBase.h>
+
+#include <dpl/assert.h>
+#include <dpl/foreach.h>
+#include <dpl/log/log.h>
+
+namespace SoupWrapper {
+
+SoupMessageSendBase::SoupMessageSendBase()
+ : m_status(STATUS_IDLE)
+ , m_timeout(30)
+ , m_tryCount(5)
+{}
+
+SoupMessageSendBase::~SoupMessageSendBase(){
+ Assert(m_status == STATUS_IDLE);
+}
+
+void SoupMessageSendBase::setHeader(const std::string &property, const std::string &value){
+ Assert(m_status == STATUS_IDLE);
+ m_headerMap[property] = value;
+}
+
+void SoupMessageSendBase::setHost(const std::string &host){
+ Assert(m_status == STATUS_IDLE);
+ m_host = host;
+}
+
+void SoupMessageSendBase::setRequest(const std::string &contentType, const MessageBuffer &message){
+ Assert(m_status == STATUS_IDLE);
+ m_requestType = contentType;
+ m_requestBuffer = message;
+}
+
+SoupMessageSendBase::MessageBuffer SoupMessageSendBase::getResponse() const {
+ Assert(m_status == STATUS_IDLE);
+ return m_responseBuffer;
+}
+
+void SoupMessageSendBase::setTimeout(int seconds) {
+ Assert(m_status == STATUS_IDLE);
+ Assert(seconds >= 0);
+ m_timeout = seconds;
+}
+
+void SoupMessageSendBase::setRetry(int retry) {
+ Assert(m_status == STATUS_IDLE);
+ Assert(retry >= 0);
+ m_tryCount = retry + 1;
+}
+
+
+SoupMessage* SoupMessageSendBase::createRequest(){
+ SoupMessage *message;
+
+ LogInfo("Soup message will be send to: " << m_host.c_str());
+
+ if (!m_requestBuffer.empty()) {
+ message = soup_message_new("POST", m_host.c_str());
+ } else {
+ message = soup_message_new("GET", m_host.c_str());
+ }
+
+ if (!message) {
+ LogError("Error creating request!");
+ return 0;
+ }
+
+ FOREACH(it, m_headerMap){
+ soup_message_headers_append(message->request_headers,
+ it->first.c_str(),
+ it->second.c_str());
+ }
+
+ if (!m_requestBuffer.empty()) {
+ soup_message_set_http_version(message, SOUP_HTTP_1_0);
+ soup_message_set_request(message,
+ m_requestType.c_str(),
+ SOUP_MEMORY_COPY,
+ &m_requestBuffer[0],
+ m_requestBuffer.size());
+ }
+// soup_message_set_flags(message, SOUP_MESSAGE_NO_REDIRECT);
+ return message;
+}
+
+} // namespace ValidationCore
--- /dev/null
+/*
+ * 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.
+ */
+/*!
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 0.1
+ * @file SoupMessageSendBase.h
+ * @brief Simple wrapper for soup.
+ */
+#ifndef _SRC_VALIDATION_CORE_SOUP_MESSAGE_SEND_BASE_H_
+#define _SRC_VALIDATION_CORE_SOUP_MESSAGE_SEND_BASE_H_
+
+#include <map>
+#include <vector>
+#include <string>
+
+#include <libsoup/soup.h>
+
+namespace SoupWrapper {
+
+class SoupMessageSendBase {
+ public:
+
+ typedef std::vector<char> MessageBuffer;
+ typedef std::map<std::string,std::string> HeaderMap;
+
+ enum RequestStatus {
+ REQUEST_STATUS_OK,
+ REQUEST_STATUS_CONNECTION_ERROR
+ };
+
+ SoupMessageSendBase();
+
+ virtual ~SoupMessageSendBase();
+
+ /**
+ * Add specific information to request header.
+ *
+ * @param[in] property property name (for example "Host")
+ * @param[in] value property value (for example "onet.pl:80")
+ */
+ void setHeader(const std::string &property,
+ const std::string &value);
+
+ /**
+ * Set request destination.
+ *
+ * @param[in] host - full path to source (http://onet.pl/index.html)
+ */
+ void setHost(const std::string &host);
+
+ /**
+ * Set body of request.
+ *
+ * @param[in] contentType (for example: "application/ocsp-request")
+ * @param[in] message body of reqeust
+ */
+ void setRequest(const std::string &contentType,
+ const MessageBuffer &message);
+
+ /**
+ * Set network timeout. Default is 30 seconds.
+ *
+ * @param[in] seconds timeout in seconds
+ */
+ void setTimeout(int seconds);
+
+ /**
+ * How many erros soup will accept before he will terminate connection.
+ * Default is 5.
+ *
+ * @param[in] retry number
+ */
+ void setRetry(int retry);
+
+ /**
+ * Get response from serwer.
+ */
+ MessageBuffer getResponse() const;
+
+ protected:
+
+ SoupMessage* createRequest();
+
+ enum Status {
+ STATUS_IDLE,
+ STATUS_SEND_SYNC,
+ STATUS_SEND_ASYNC
+ };
+
+ Status m_status;
+
+ int m_timeout;
+ int m_tryCount;
+
+ std::string m_host;
+ std::string m_requestType;
+ MessageBuffer m_requestBuffer;
+ MessageBuffer m_responseBuffer;
+ HeaderMap m_headerMap;
+};
+
+} // namespace ValidationCore
+
+#endif
--- /dev/null
+/*
+ * 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.
+ */
+/*!
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 0.1
+ * @file SoupMessageSendSync.cpp
+ * @brief Implementation of soup synchronous interface.
+ */
+#include <vcore/SoupMessageSendSync.h>
+
+#include <memory>
+#include <functional>
+
+#include <vconf.h>
+
+#include <dpl/log/log.h>
+
+namespace SoupWrapper {
+
+SoupMessageSendBase::RequestStatus SoupMessageSendSync::sendSync()
+{
+ Assert(m_status == STATUS_IDLE);
+ m_status = STATUS_SEND_SYNC;
+
+ ScopedGMainContext context(g_main_context_new());
+
+ std::unique_ptr<char,std::function<void(void*)> >
+ proxy(vconf_get_str(VCONFKEY_NETWORK_PROXY), free);
+
+ std::unique_ptr <SoupURI, std::function<void(SoupURI*)> >
+ proxyURI(soup_uri_new (proxy.get()), soup_uri_free);
+
+ LogDebug("Proxy ptr:" << (void*)proxy.get() <<
+ " Proxy addr: " << proxy.get());
+
+ for(int tryCount = 0; tryCount < m_tryCount; ++ tryCount){
+ LogDebug("Try(" << tryCount << ") to download " << m_host);
+
+ ScopedSoupSession session(soup_session_async_new_with_options(
+ SOUP_SESSION_ASYNC_CONTEXT,
+ &*context,
+ SOUP_SESSION_TIMEOUT,
+ m_timeout,
+ SOUP_SESSION_PROXY_URI,
+ proxyURI.get(),
+ NULL));
+
+ ScopedSoupMessage msg;
+
+ msg.Reset(createRequest());
+
+ if (!msg) {
+ LogError("Unable to send HTTP request.");
+ m_status = STATUS_IDLE;
+ return REQUEST_STATUS_CONNECTION_ERROR;
+ }
+ soup_session_send_message(&*session, &*msg);
+
+ // if (SOUP_STATUS_IS_SUCCESSFUL(msg->status_code))
+
+ if (msg->status_code == SOUP_STATUS_OK) {
+ m_responseBuffer.resize(msg->response_body->length);
+ memcpy(&m_responseBuffer[0],
+ msg->response_body->data,
+ msg->response_body->length);
+ // We are done.
+ m_status = STATUS_IDLE;
+ return REQUEST_STATUS_OK;
+ } else {
+ LogWarning("Soup failed with code " << msg->status_code
+ << " message \n------------\n"
+ << msg->response_body->data
+ << "\n--------------\n");
+ }
+ }
+
+ m_status = STATUS_IDLE;
+ return REQUEST_STATUS_CONNECTION_ERROR;
+}
+
+} // namespave ValidationCore
--- /dev/null
+/*
+ * 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.
+ */
+/*!
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 0.1
+ * @file SoupMessageSendSync.h
+ * @brief Wrapper for soup synchronous interface.
+ */
+#ifndef _VALIDATION_CORE_SOUP_MESSAGE_SEND_SYNC_H_
+#define _VALIDATION_CORE_SOUP_MESSAGE_SEND_SYNC_H_
+
+#include <vcore/SoupMessageSendBase.h>
+
+#include <vcore/scoped_gpointer.h>
+
+namespace SoupWrapper {
+
+class SoupMessageSendSync : public SoupMessageSendBase {
+ public:
+ RequestStatus sendSync();
+ protected:
+ typedef WRT::ScopedGPointer<SoupMessage> ScopedSoupMessage;
+ typedef WRT::ScopedGPointer<SoupSession> ScopedSoupSession;
+ typedef WRT::ScopedGPointer<GMainContext> ScopedGMainContext;
+};
+
+} // namespace ValidationCore
+
+#endif
--- /dev/null
+/*
+ * 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.
+ */
+#include <vcore/TimeConversion.h>
+
+#include <string.h>
+
+#include <dpl/log/log.h>
+#include <dpl/assert.h>
+
+namespace ValidationCore {
+
+int asn1TimeToTimeT(ASN1_TIME *t, time_t *res)
+{
+ struct tm tm;
+ int offset;
+
+ (*res) = 0;
+ if (!ASN1_TIME_check(t)) {
+ return -1;
+ }
+
+ memset(&tm, 0, sizeof(tm));
+
+#define g2(p) (((p)[0] - '0') * 10 + (p)[1] - '0')
+ if (t->type == V_ASN1_UTCTIME) {
+ Assert(t->length > 12);
+
+ /* this code is copied from OpenSSL asn1/a_utctm.c file */
+ tm.tm_year = g2(t->data);
+ if (tm.tm_year < 50) {
+ tm.tm_year += 100;
+ }
+ tm.tm_mon = g2(t->data + 2) - 1;
+ tm.tm_mday = g2(t->data + 4);
+ tm.tm_hour = g2(t->data + 6);
+ tm.tm_min = g2(t->data + 8);
+ tm.tm_sec = g2(t->data + 10);
+ if (t->data[12] == 'Z') {
+ offset = 0;
+ } else {
+ Assert(t->length > 16);
+
+ offset = g2(t->data + 13) * 60 + g2(t->data + 15);
+ if (t->data[12] == '-') {
+ offset = -offset;
+ }
+ }
+ tm.tm_isdst = -1;
+ } else {
+ Assert(t->length > 14);
+
+ tm.tm_year = g2(t->data) * 100 + g2(t->data + 2);
+ tm.tm_mon = g2(t->data + 4) - 1;
+ tm.tm_mday = g2(t->data + 6);
+ tm.tm_hour = g2(t->data + 8);
+ tm.tm_min = g2(t->data + 10);
+ tm.tm_sec = g2(t->data + 12);
+ if (t->data[14] == 'Z') {
+ offset = 0;
+ } else {
+ Assert(t->length > 18);
+
+ offset = g2(t->data + 15) * 60 + g2(t->data + 17);
+ if (t->data[14] == '-') {
+ offset = -offset;
+ }
+ }
+ tm.tm_isdst = -1;
+ }
+#undef g2
+ (*res) = timegm(&tm) - offset * 60;
+ return 0;
+}
+
+int asn1GeneralizedTimeToTimeT(ASN1_GENERALIZEDTIME *tm, time_t *res)
+{
+ /*
+ * This code is based on following assumption:
+ * from openssl/a_gentm.c:
+ * GENERALIZEDTIME is similar to UTCTIME except the year is
+ * represented as YYYY. This stuff treats everything as a two digit
+ * field so make first two fields 00 to 99
+ */
+ const int DATE_BUFFER_LENGTH = 15; // YYYYMMDDHHMMSSZ
+
+ if (NULL == res || NULL == tm) {
+ LogError("NULL pointer");
+ return -1;
+ }
+
+ if (DATE_BUFFER_LENGTH != tm->length || NULL == tm->data) {
+ LogError("Invalid ASN1_GENERALIZEDTIME");
+ return -1;
+ }
+
+ struct tm time_s;
+ if (sscanf ((char*)tm->data,
+ "%4d%2d%2d%2d%2d%2d",
+ &time_s.tm_year,
+ &time_s.tm_mon,
+ &time_s.tm_mday,
+ &time_s.tm_hour,
+ &time_s.tm_min,
+ &time_s.tm_sec) < 6)
+ {
+ LogError("Could not extract time data from ASN1_GENERALIZEDTIME");
+ return -1;
+ }
+
+ time_s.tm_year -= 1900;
+ time_s.tm_mon -= 1;
+ time_s.tm_isdst = 0; // UTC
+ time_s.tm_gmtoff = 0; // UTC
+ time_s.tm_zone = NULL; // UTC
+
+ *res = mktime(&time_s);
+
+ return 0;
+}
+
+} // namespace ValidationCore
+
--- /dev/null
+/*
+ * 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 TimeConversion.h
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 0.1
+ * @brief
+ */
+#ifndef _VALIDATION_CORE_TIMECONVERSION_H_
+#define _VALIDATION_CORE_TIMECONVERSION_H_
+
+#include <ctime>
+
+#include <openssl/x509.h>
+
+namespace ValidationCore {
+// from OpenSSL asn1/a_utctm.c code
+int asn1TimeToTimeT(ASN1_TIME *t, time_t *res);
+
+int asn1GeneralizedTimeToTimeT(ASN1_GENERALIZEDTIME *tm,
+ time_t *res);
+} // namespace ValidationCore
+
+#endif // _VALIDATION_CORE_TIMECONVERSION_H_
+
--- /dev/null
+/*
+ * 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 VCore.cpp
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @brief
+ */
+
+#include <vcore/VCorePrivate.h>
+#include <vcore/Config.h>
+#include <vcore/Database.h>
+#include <openssl/ssl.h>
+#include <database_checksum_vcore.h>
+#include <glib.h>
+#include <glib-object.h>
+
+#include <dpl/assert.h>
+#include <dpl/log/log.h>
+
+namespace {
+DPL::DB::ThreadDatabaseSupport *threadInterface = NULL;
+} // namespace anonymous
+
+namespace ValidationCore {
+
+void AttachToThreadRO(void)
+{
+ Assert(threadInterface);
+ static bool check = true;
+ threadInterface->AttachToThread(
+ DPL::DB::SqlConnection::Flag::RO);
+ // We can have race condition here but CheckTableExist
+ // is thread safe and nothing bad will happend.
+ if (check) {
+ check = false;
+ Assert(ThreadInterface().CheckTableExist(DB_CHECKSUM_STR) &&
+ "Not a valid vcore database version");
+ }
+}
+
+void AttachToThreadRW(void)
+{
+ Assert(threadInterface);
+ static bool check = true;
+ threadInterface->AttachToThread(
+ DPL::DB::SqlConnection::Flag::RW);
+ // We can have race condition here but CheckTableExist
+ // is thread safe and nothing bad will happend.
+ if (check) {
+ check = false;
+ Assert(ThreadInterface().CheckTableExist(DB_CHECKSUM_STR) &&
+ "Not a valid vcore database version");
+ }
+}
+
+void DetachFromThread(void){
+ Assert(threadInterface);
+ threadInterface->DetachFromThread();
+}
+
+DPL::DB::ThreadDatabaseSupport& ThreadInterface(void) {
+ Assert(threadInterface);
+ return *threadInterface;
+}
+
+bool VCoreInit(const std::string& configFilePath,
+ const std::string& configSchemaPath,
+ const std::string& databasePath)
+{
+ if(threadInterface) {
+ LogDebug("Already Initialized");
+ return false;
+ }
+
+ threadInterface = new DPL::DB::ThreadDatabaseSupport(
+ databasePath.c_str(),
+ DPL::DB::SqlConnection::Flag::UseLucene);
+
+ SSL_library_init();
+// g_thread_init(NULL);
+ g_type_init();
+
+ LogDebug("Initializing VCore");
+ Config &globalConfig = ConfigSingleton::Instance();
+ bool returnValue = globalConfig.setXMLConfigPath(configFilePath) &&
+ globalConfig.setXMLSchemaPath(configSchemaPath);
+
+ return returnValue;
+}
+
+void VCoreDeinit()
+{
+ Assert(threadInterface && "Not initialized or already deinitialized");
+ delete threadInterface;
+ threadInterface = NULL;
+}
+
+} // namespace ValidationCore
+
--- /dev/null
+/*
+ * 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 VCore.h
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief
+ */
+#ifndef _VCORE_SRC_VCORE_VCORE_H_
+#define _VCORE_SRC_VCORE_VCORE_H_
+
+#include <string>
+
+namespace ValidationCore {
+/*
+ * configFilePath - path to XML config file with certificates configuration
+ *
+ * configSchemaPath - XMLschema of config file
+ *
+ * databasePath - path to database with OCSP/CRL cache.
+ *
+ * This function could be run only once. If you call it twice it will
+ * return false and non data will be set.
+ *
+ * This function must be call before AttachToThread function.
+ */
+bool VCoreInit(const std::string& configFilePath,
+ const std::string& configSchemaPath,
+ const std::string& databasePath);
+
+/*
+ * This function will free internal structures responsible for db connection.
+ */
+void VCoreDeinit(void);
+
+/*
+ * All thread with are using OCSP/CRL must call AttachToThread function before
+ * it can call OCSP/CRL. More than one thread could be Attach with OCPS/CRL.
+ *
+ * You mast attach thread to OCSP/CRL because OCSP/CRL is using database
+ * CertificateCachedDAO. For each thread that will be using this database
+ * vcore must create internal structure (with connection info).
+ *
+ */
+void AttachToThreadRO(void);
+void AttachToThreadRW(void);
+void DetachFromThread(void);
+
+} // namespace ValidationCore
+
+#endif // _VCORE_SRC_VCORE_VCORE_H_
+
--- /dev/null
+/*
+ * 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 VCore.h
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief
+ */
+#ifndef _VCORE_SRC_VCORE_VCOREPRIVATE_H_
+#define _VCORE_SRC_VCORE_VCOREPRIVATE_H_
+
+#include <string>
+#include <VCore.h>
+#include <database_checksum_vcore.h>
+#include <dpl/db/thread_database_support.h>
+
+namespace ValidationCore {
+DPL::DB::ThreadDatabaseSupport& ThreadInterface(void);
+} // namespace ValidationCore
+
+#endif // _VCORE_SRC_VCORE_VCORE_H_
+
--- /dev/null
+/*
+ * 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 <list>
+#include <set>
+#include <string>
+
+namespace ValidationCore {
+
+/*
+ * base deleter func
+ */
+template <typename T>
+struct ValidatorCoreUniversalFree {};
+
+// Template Specialization
+#define VC_DECLARE_DELETER(type, function) \
+ template <> \
+ struct ValidatorCoreUniversalFree <type> { \
+ void universal_free(type *ptr){ \
+ if (ptr) { \
+ function(ptr); } \
+ } \
+ };
+
+template <typename T>
+class AutoPtr
+{
+ public:
+ AutoPtr(T *ptr) :
+ m_data(ptr)
+ {
+ }
+
+ AutoPtr(const AutoPtr<T> &second)
+ {
+ m_data = second.m_data;
+ second.m_data = 0;
+ }
+
+ AutoPtr & operator=(const AutoPtr &second)
+ {
+ if (this != &second) {
+ ValidatorCoreUniversalFree<T> 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<T> 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_
--- /dev/null
+/*
+ * 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
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief
+ */
+#include <vcore/ValidatorFactories.h>
+
+#include <string>
+#include <dpl/log/log.h>
+
+#include <vcore/Certificate.h>
+#include <vcore/CertificateConfigReader.h>
+#include <vcore/Config.h>
+
+namespace ValidationCore {
+
+const CertificateIdentifier& createCertificateIdentifier()
+{
+ static CertificateIdentifier certificateIdentifier;
+ static bool initialized = false;
+ if (!initialized) {
+ CertificateConfigReader reader;
+ std::string file =
+ ConfigSingleton::Instance().getXMLConfigPath();
+ LogDebug("File with fingerprint list is: " << file);
+ std::string schema =
+ ConfigSingleton::Instance().getXMLSchemaPath();
+ LogDebug("File with fingerprint list schema is: " << schema);
+ reader.initialize(file, schema);
+ reader.read(certificateIdentifier);
+ initialized = true;
+ }
+ return certificateIdentifier;
+}
+
+} // namespace ValidationCore
--- /dev/null
+/*
+ * 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
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief
+ */
+#ifndef _WRT_ENGINE_SRC_INSTALLER_CORE_VALIDATION_CORE_VALIDATORFACTORY_H_
+#define _WRT_ENGINE_SRC_INSTALLER_CORE_VALIDATION_CORE_VALIDATORFACTORY_H_
+
+#include <CertificateIdentifier.h>
+
+namespace ValidationCore {
+// First use of CertificateIdentificator should initialized it.
+// We do not want to create cyclic dependencies between
+// CertificateConfigReader and CertificateIdentificator so
+// we are using factory method to create CertificateIdentificator.
+
+const CertificateIdentifier& createCertificateIdentifier();
+} // namespace ValidationCore
+
+#endif // _WRT_ENGINE_SRC_INSTALLER_CORE_VALIDATION_CORE_VALIDATORFACTORY_H_
--- /dev/null
+/*
+ * 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.
+ */
+/*!
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 0.2
+ * @file VerficationStatus.cpp
+ * @brief OCSP/CRL status.
+ */
+#include <vcore/VerificationStatus.h>
+
+namespace ValidationCore {
+
+VerificationStatusSet::VerificationStatusSet()
+ : m_verdictMap(0)
+{}
+
+void VerificationStatusSet::add(VerificationStatus status) {
+ m_verdictMap |= status;
+}
+
+bool VerificationStatusSet::contains(VerificationStatus status) const {
+ return m_verdictMap & status;
+}
+
+bool VerificationStatusSet::isEmpty() const {
+ return 0 == m_verdictMap;
+}
+
+void VerificationStatusSet::operator+=(const VerificationStatusSet &second) {
+ m_verdictMap |= second.m_verdictMap;
+}
+
+void VerificationStatusSet::reset() {
+ m_verdictMap = 0;
+}
+
+VerificationStatus VerificationStatusSet::convertToStatus() const
+{
+ if (m_verdictMap & VERIFICATION_STATUS_REVOKED) {
+ return VERIFICATION_STATUS_REVOKED;
+ }
+
+ if (m_verdictMap & VERIFICATION_STATUS_VERIFICATION_ERROR) {
+ return VERIFICATION_STATUS_VERIFICATION_ERROR;
+ }
+
+ if (m_verdictMap & VERIFICATION_STATUS_ERROR) {
+ return VERIFICATION_STATUS_ERROR;
+ }
+
+ if (m_verdictMap & VERIFICATION_STATUS_UNKNOWN) {
+ return VERIFICATION_STATUS_UNKNOWN;
+ }
+
+ if (m_verdictMap & VERIFICATION_STATUS_CONNECTION_FAILED) {
+ return VERIFICATION_STATUS_CONNECTION_FAILED;
+ }
+
+ if (m_verdictMap & VERIFICATION_STATUS_NOT_SUPPORT) {
+ return VERIFICATION_STATUS_NOT_SUPPORT;
+ }
+
+ if (m_verdictMap & VERIFICATION_STATUS_GOOD) {
+ return VERIFICATION_STATUS_GOOD;
+ }
+
+ return VERIFICATION_STATUS_ERROR;
+}
+} // namespace ValidationCore
--- /dev/null
+/*
+ * 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.
+ */
+/*!
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 0.2
+ * @file VerificationStatus.h
+ * @brief OCSP/CRL status.
+ */
+#ifndef _VALIDATION_CORE_VERIFICATION_STATUS_H_
+#define _VALIDATION_CORE_VERIFICATION_STATUS_H_
+
+namespace ValidationCore {
+enum VerificationStatus
+{
+ //! The certificate has not been revoked.
+ /*! Connection to OCSP responder was successful and the certificate
+ * has not been revoked.
+ */
+ VERIFICATION_STATUS_GOOD = 1,
+
+ //! The certificate has been revoked.
+ /*! Connection to OCSP responder was successful and the certificate
+ * has been revoked.
+ * RFC2560: "The "revoked" state indicates that the certificate has
+ * been revoked (either permanantly or temporarily
+ * (on hold))."
+ */
+ VERIFICATION_STATUS_REVOKED = 1 << 1,
+
+ //! The certificate status is unknown.
+ /*! Connection to OCSP responder was successful and the certificate
+ * has unknown status.
+ *
+ * RFC2560: "The "unknown" state indicates that the responder
+ * doesn't know about the certificate being requested."
+ */
+ VERIFICATION_STATUS_UNKNOWN = 1 << 2,
+
+ //! The certificate status was not figure out.
+ /*! The response from ocsp/crl server contains broken signature. */
+ VERIFICATION_STATUS_VERIFICATION_ERROR = 1 << 3,
+
+ //! The certificate status was not figure out.
+ /*! The certificate does not contain ocsp/crl extension. */
+ VERIFICATION_STATUS_NOT_SUPPORT = 1 << 4,
+
+ //! The certificate status was not figure out.
+ /*! The CertMgr could not connect to OCSP responder. */
+ VERIFICATION_STATUS_CONNECTION_FAILED = 1 << 5,
+
+ //! The certificate status is unknown due to internal error inside OCSP
+ VERIFICATION_STATUS_ERROR = 1 << 6
+};
+
+class VerificationStatusSet
+{
+ public:
+ VerificationStatusSet();
+
+ void add(VerificationStatus status);
+
+ bool contains(VerificationStatus status) const;
+
+ bool isEmpty() const;
+
+ void operator+=(const VerificationStatusSet &second);
+
+ void reset();
+
+ VerificationStatus convertToStatus() const;
+
+ private:
+ unsigned int m_verdictMap;
+};
+
+/* TODO this status should be defined in wrt-engine sources */
+enum WidgetVerificationStatus
+{
+ // All certificate has been veficated and all certificates are good.
+ // Widget is able to be installed.
+ WIDGET_VERIFICATION_STATUS_GOOD,
+ // Some certificate has been revoked. Widget is not able to be installed.
+ WIDGET_VERIFICATION_STATUS_REVOKED,
+};
+
+} // namespace ValidationCore
+
+#endif // _VALIDATION_CORE_VERIFICATION_STATUS_H_
--- /dev/null
+/*
+ * 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
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief
+ */
+#include "WacOrigin.h"
+
+#include <algorithm>
+#include <ctype.h>
+#include <idna.h>
+
+#include <<dpl/log/log.h>>
+
+#include <iri.h>
+#include "ValidatorCommon.h"
+
+namespace {
+const std::string SCHEME_HTTP = "http";
+const std::string SCHEME_HTTPS = "https";
+const int PORT_HTTP = 80;
+const int PORT_HTTPS = 443;
+}
+
+namespace ValidationCore {
+VC_DECLARE_DELETER(iri_struct, iri_destroy)
+
+WacOrigin::WacOrigin(const std::string &url) :
+ m_port(0),
+ m_parseFailed(false)
+{
+ parse(url.c_str());
+}
+
+WacOrigin::WacOrigin(const char *url) :
+ m_port(0),
+ m_parseFailed(false)
+{
+ parse(url);
+}
+
+bool WacOrigin::operator==(const WacOrigin &second) const
+{
+ if (m_parseFailed || second.m_parseFailed) {
+ return false;
+ }
+
+ return (m_scheme == second.m_scheme) &&
+ (m_host == second.m_host) &&
+ (m_port == second.m_port);
+}
+
+void WacOrigin::parse(const char *url)
+{
+ // Step are taken from algorihtm:
+ // http://www.w3.org/TR/html5/origin-0.html#origin-0
+
+ // Step 1
+ // Step 2
+ AutoPtr<iri_struct> iri(iri_parse(url));
+ if (!iri.get()) {
+ m_parseFailed = true;
+ return;
+ }
+
+ if (iri->scheme) {
+ m_scheme = iri->scheme;
+ } else {
+ m_parseFailed = true;
+ return;
+ }
+
+ // Step 3 - Skip this point.
+ // WAC 2.0 PRV - we are suport only "http" and "https" schemas.
+
+ // Step 4 - Todo
+
+ // Step 5
+ std::transform(m_scheme.begin(), m_scheme.end(), m_scheme.begin(), tolower);
+
+ // Step 6 - we only support "http" and "https" schemas
+ if ((m_scheme != SCHEME_HTTP) && (m_scheme != SCHEME_HTTPS)) {
+ m_parseFailed = true;
+ return;
+ }
+
+ // Step 7 - Skip. We do not support "file" schema.
+
+ // Step 8
+ if (iri->host) {
+ m_host = iri->host;
+ } else {
+ m_parseFailed = true;
+ return;
+ }
+
+ // Step 9
+ char *output = NULL;
+ if (IDNA_SUCCESS !=
+ idna_to_ascii_lz(m_host.c_str(), &output, IDNA_USE_STD3_ASCII_RULES)) {
+ LogError("libidn error");
+ m_parseFailed = true;
+ free(output);
+ return;
+ }
+ m_host = output;
+ free(output);
+
+ // Step 10
+ std::transform(m_host.begin(), m_host.end(), m_host.begin(), ::tolower);
+
+ // Step 11
+ if (iri->port) {
+ m_port = iri->port;
+ } else {
+ setPort();
+ }
+
+ // Step 12 - Skip it. We do not return anything.
+ // User should create geters if he need access to schema/host/port.
+}
+
+void WacOrigin::setPort()
+{
+ if (SCHEME_HTTP == m_scheme) {
+ m_port = PORT_HTTP;
+ return;
+ } else if (SCHEME_HTTPS == m_scheme) {
+ m_port = PORT_HTTPS;
+ return;
+ } else {
+ LogDebug("Scheme " << m_scheme << " is not support by WAC2.0");
+ m_parseFailed = true;
+ }
+}
+} // namespace ValidationCore
--- /dev/null
+/*
+ * 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
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief This is stub for HTML5Origin implementation.
+ * This implementation is compatible with WAC 2.0 PRV requirements
+ * and is _not_ full compatible with ORIGIN algorithm requirements
+ * defined in http://www.w3.org/TR/html5/origin-0.html#origin-0
+ */
+#ifndef _WRT_ENGINE_SRC_INSTALLER_CORE_VALIDATION_CORE_HTML5ORIGIN_H_
+#define _WRT_ENGINE_SRC_INSTALLER_CORE_VALIDATION_CORE_HTML5ORIGIN_H_
+
+#include <string>
+
+namespace ValidationCore {
+class WacOrigin
+{
+ public:
+
+ WacOrigin(const std::string &url);
+ WacOrigin(const char *url);
+
+ bool operator!=(const WacOrigin &second) const
+ {
+ return !(operator==(second));
+ }
+
+ bool operator==(const WacOrigin &second) const;
+
+ private:
+ void parse(const char *url);
+ void setPort();
+
+ std::string m_scheme;
+ std::string m_host;
+ int m_port;
+ bool m_parseFailed; // if parsing failed we should return unique identifier
+};
+} //namespace ValidationCore
+
+#endif // _WRT_ENGINE_SRC_INSTALLER_CORE_VALIDATION_CORE_HTML5ORIGIN_H_
--- /dev/null
+/*
+ * 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 WrtSignatureValidator.cpp
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief Implementatin of tizen signature validation protocol.
+ */
+#include <vcore/WrtSignatureValidator.h>
+
+#include <dpl/log/log.h>
+
+#include <vcore/CertificateVerifier.h>
+#include <vcore/Certificate.h>
+#include <vcore/OCSPCertMgrUtil.h>
+#include <vcore/ReferenceValidator.h>
+#include <vcore/ValidatorFactories.h>
+#include <vcore/XmlsecAdapter.h>
+
+namespace {
+const time_t TIMET_DAY = 60 * 60 * 24;
+
+const std::string TOKEN_ROLE_AUTHOR_URI =
+ "http://www.w3.org/ns/widgets-digsig#role-author";
+const std::string TOKEN_ROLE_DISTRIBUTOR_URI =
+ "http://www.w3.org/ns/widgets-digsig#role-distributor";
+const std::string TOKEN_PROFILE_URI =
+ "http://www.w3.org/ns/widgets-digsig#profile";
+} // namespace anonymouse
+
+namespace ValidationCore {
+
+class WrtSignatureValidator::Impl {
+public:
+ virtual WrtSignatureValidator::Result check(
+ SignatureData &data,
+ const std::string &widgetContentPath) = 0;
+
+ explicit Impl(bool ocspEnable,
+ bool crlEnable,
+ bool complianceMode)
+ : m_ocspEnable(ocspEnable)
+ , m_crlEnable(crlEnable)
+ , m_complianceModeEnabled(complianceMode)
+ {}
+
+ virtual ~Impl(){}
+
+ bool checkRoleURI(const SignatureData &data) {
+ std::string roleURI = data.getRoleURI();
+
+ if (roleURI.empty()) {
+ LogWarning("URI attribute in Role tag couldn't be empty.");
+ return false;
+ }
+
+ if (roleURI != TOKEN_ROLE_AUTHOR_URI && data.isAuthorSignature()) {
+ LogWarning("URI attribute in Role tag does not "
+ "match with signature filename.");
+ return false;
+ }
+
+ if (roleURI != TOKEN_ROLE_DISTRIBUTOR_URI && !data.isAuthorSignature()) {
+ LogWarning("URI attribute in Role tag does not "
+ "match with signature filename.");
+ return false;
+ }
+ return true;
+ }
+
+ bool checkProfileURI(const SignatureData &data) {
+ if (TOKEN_PROFILE_URI != data.getProfileURI()) {
+ LogWarning(
+ "Profile tag contains unsupported value in URI attribute(" <<
+ data.getProfileURI() << ").");
+ return false;
+ }
+ return true;
+ }
+
+ bool checkObjectReferences(const SignatureData &data) {
+ ObjectList objectList = data.getObjectList();
+ ObjectList::const_iterator iter;
+ for (iter = objectList.begin(); iter != objectList.end(); ++iter) {
+ if (!data.containObjectReference(*iter)) {
+ LogWarning("Signature does not contain reference for object " <<
+ *iter);
+ return false;
+ }
+ }
+ return true;
+ }
+protected:
+ bool m_ocspEnable;
+ bool m_crlEnable;
+ bool m_complianceModeEnabled;
+};
+
+class ImplTizen : public WrtSignatureValidator::Impl
+{
+ public:
+ WrtSignatureValidator::Result check(SignatureData &data,
+ const std::string &widgetContentPath);
+
+ explicit ImplTizen(bool ocspEnable,
+ bool crlEnable,
+ bool complianceMode)
+ : Impl(ocspEnable, crlEnable, complianceMode)
+ {}
+
+ virtual ~ImplTizen() {}
+};
+
+WrtSignatureValidator::Result ImplTizen::check(
+ SignatureData &data,
+ const std::string &widgetContentPath)
+{
+ bool disregard = false;
+
+ if (!checkRoleURI(data)) {
+ return WrtSignatureValidator::SIGNATURE_INVALID;
+ }
+
+ if (!checkProfileURI(data)) {
+ return WrtSignatureValidator::SIGNATURE_INVALID;
+ }
+
+ // CertificateList sortedCertificateList = data.getCertList();
+
+ CertificateCollection collection;
+ collection.load(data.getCertList());
+
+ // First step - sort certificate
+ if (!collection.sort()) {
+ LogWarning("Certificates do not form valid chain.");
+ return WrtSignatureValidator::SIGNATURE_INVALID;
+ }
+
+ // Check for error
+ if (collection.empty()) {
+ LogWarning("Certificate list in signature is empty.");
+ return WrtSignatureValidator::SIGNATURE_INVALID;
+ }
+
+ CertificateList sortedCertificateList = collection.getChain();
+
+ // TODO move it to CertificateCollection
+ // Add root CA and CA certificates (if chain is incomplete)
+ sortedCertificateList =
+ OCSPCertMgrUtil::completeCertificateChain(sortedCertificateList);
+
+ CertificatePtr root = sortedCertificateList.back();
+
+ // Is Root CA certificate trusted?
+ CertStoreId::Set storeIdSet = createCertificateIdentifier().find(root);
+
+ LogDebug("Is root certificate from WAC_PUBLISHER domain: "
+ << storeIdSet.contains(CertStoreId::WAC_PUBLISHER));
+ LogDebug("Is root certificate from WAC_DEVELOPER domain: "
+ << storeIdSet.contains(CertStoreId::DEVELOPER));
+ LogDebug("Is root certificate from WAC_ROOT domain: "
+ << storeIdSet.contains(CertStoreId::WAC_ROOT));
+ LogDebug("Is root certificate from WAC_MEMBER domain: "
+ << storeIdSet.contains(CertStoreId::WAC_MEMBER));
+ LogDebug("Is root certificate from TIZEN_MEMBER domain: "
+ << storeIdSet.contains(CertStoreId::TIZEN_MEMBER));
+ LogDebug("Is root certificate from TIZEN_ORANGE domain: "
+ << storeIdSet.contains(CertStoreId::ORANGE_LEGACY));
+
+ // WAC chapter 3.2.1 - verified definition
+ if (data.isAuthorSignature()) {
+ if (!storeIdSet.contains(CertStoreId::WAC_PUBLISHER)) {
+ LogWarning("Author signature has got unrecognized Root CA "
+ "certificate. Signature will be disregarded.");
+ disregard = true;
+ }
+ LogDebug("Root CA for author signature is correct.");
+ } else {
+ if (!storeIdSet.contains(CertStoreId::DEVELOPER) &&
+ !storeIdSet.contains(CertStoreId::TIZEN_MEMBER))
+ {
+ LogWarning("Distiributor signature has got unrecognized Root CA "
+ "certificate. Signature will be disregarded.");
+ disregard = true;
+ } else
+ LogDebug("Root CA for distributor signature is correct.");
+ }
+
+ data.setStorageType(storeIdSet);
+ data.setSortedCertificateList(sortedCertificateList);
+
+ // We add only Root CA certificate because WAC ensure that the rest
+ // of certificates are present in signature files ;-)
+ XmlSec::XmlSecContext context;
+ context.signatureFile = data.getSignatureFileName();
+ context.certificatePtr = root;
+
+ // Now we should have full certificate chain.
+ // If the end certificate is not ROOT CA we should disregard signature
+ // but still signature must be valid... Aaaaaa it's so stupid...
+ if (!(root->isSignedBy(root))) {
+ LogWarning("Root CA certificate not found. Chain is incomplete.");
+ context.allowBrokenChain = true;
+ }
+
+ // WAC 2.0 SP-2066 The wrt must not block widget installation
+ // due to expiration of the author certificate.
+ time_t notAfter = data.getEndEntityCertificatePtr()->getNotAfter();
+ bool expired = notAfter < time(NULL);
+ if (data.isAuthorSignature() && expired) {
+ context.validationTime = notAfter - TIMET_DAY;
+ }
+ // end
+
+ if (XmlSec::NO_ERROR != XmlSecSingleton::Instance().validate(&context)) {
+ LogWarning("Installation break - invalid package!");
+ return WrtSignatureValidator::SIGNATURE_INVALID;
+ }
+
+ data.setReference(context.referenceSet);
+
+ if (!checkObjectReferences(data)) {
+ return WrtSignatureValidator::SIGNATURE_INVALID;
+ }
+
+ ReferenceValidator fileValidator(widgetContentPath);
+ if (ReferenceValidator::NO_ERROR != fileValidator.checkReferences(data)) {
+ LogWarning("Invalid package - file references broken");
+ return WrtSignatureValidator::SIGNATURE_INVALID;
+ }
+
+ // It is good time to do OCSP check
+ // ocspCheck will throw an exception on any error.
+ // TODO Probably we should catch this exception and add
+ // some information to SignatureData.
+ if (!m_complianceModeEnabled && !data.isAuthorSignature()) {
+ CertificateCollection coll;
+ coll.load(sortedCertificateList);
+
+ if (!coll.sort()) {
+ LogDebug("Collection does not contain chain!");
+ return WrtSignatureValidator::SIGNATURE_INVALID;
+ }
+
+ // If ORANGE_LEGACY is set we cannot check ocsp
+ bool runOCSP = storeIdSet.contains(CertStoreId::ORANGE_LEGACY) ?
+ false : m_ocspEnable;
+
+ CertificateVerifier verificator(runOCSP, m_crlEnable);
+ VerificationStatus result = verificator.check(coll);
+
+ if (result == VERIFICATION_STATUS_REVOKED) {
+ return WrtSignatureValidator::SIGNATURE_REVOKED;
+ }
+
+ if (result == VERIFICATION_STATUS_UNKNOWN ||
+ result == VERIFICATION_STATUS_ERROR)
+ {
+ disregard = true;
+ }
+ }
+
+ if (disregard) {
+ LogWarning("Signature is disregard.");
+ return WrtSignatureValidator::SIGNATURE_DISREGARD;
+ }
+ return WrtSignatureValidator::SIGNATURE_VERIFIED;
+}
+
+class ImplWac : public WrtSignatureValidator::Impl
+{
+ public:
+ WrtSignatureValidator::Result check(SignatureData &data,
+ const std::string &widgetContentPath);
+
+ explicit ImplWac(bool ocspEnable,
+ bool crlEnable,
+ bool complianceMode)
+ : Impl(ocspEnable, crlEnable, complianceMode)
+ {}
+
+ virtual ~ImplWac() {}
+};
+
+WrtSignatureValidator::Result ImplWac::check(
+ SignatureData &data,
+ const std::string &widgetContentPath)
+{
+ bool disregard = false;
+
+ if (!checkRoleURI(data)) {
+ return WrtSignatureValidator::SIGNATURE_INVALID;
+ }
+
+ if (!checkProfileURI(data)) {
+ return WrtSignatureValidator::SIGNATURE_INVALID;
+ }
+
+ // CertificateList sortedCertificateList = data.getCertList();
+
+ CertificateCollection collection;
+ collection.load(data.getCertList());
+
+ // First step - sort certificate
+ if (!collection.sort()) {
+ LogWarning("Certificates do not form valid chain.");
+ return WrtSignatureValidator::SIGNATURE_INVALID;
+ }
+
+ // Check for error
+ if (collection.empty()) {
+ LogWarning("Certificate list in signature is empty.");
+ return WrtSignatureValidator::SIGNATURE_INVALID;
+ }
+
+ CertificateList sortedCertificateList = collection.getChain();
+
+ // TODO move it to CertificateCollection
+ // Add root CA and CA certificates (if chain is incomplete)
+ sortedCertificateList =
+ OCSPCertMgrUtil::completeCertificateChain(sortedCertificateList);
+
+ CertificatePtr root = sortedCertificateList.back();
+
+ // Is Root CA certificate trusted?
+ CertStoreId::Set storeIdSet = createCertificateIdentifier().find(root);
+
+ LogDebug("Is root certificate from WAC_PUBLISHER domain: "
+ << storeIdSet.contains(CertStoreId::WAC_PUBLISHER));
+ LogDebug("Is root certificate from WAC_DEVELOPER domain: "
+ << storeIdSet.contains(CertStoreId::DEVELOPER));
+ LogDebug("Is root certificate from WAC_ROOT domain: "
+ << storeIdSet.contains(CertStoreId::WAC_ROOT));
+ LogDebug("Is root certificate from WAC_MEMBER domain: "
+ << storeIdSet.contains(CertStoreId::WAC_MEMBER));
+ LogDebug("Is root certificate from TIZEN_MEMBER domain: "
+ << storeIdSet.contains(CertStoreId::TIZEN_MEMBER));
+ LogDebug("Is root certificate from ORANGE_LEGACY domain: "
+ << storeIdSet.contains(CertStoreId::ORANGE_LEGACY));
+
+ // WAC chapter 3.2.1 - verified definition
+ if (data.isAuthorSignature()) {
+ if (!storeIdSet.contains(CertStoreId::WAC_PUBLISHER)) {
+ LogWarning("Author signature has got unrecognized Root CA "
+ "certificate. Signature will be disregarded.");
+ disregard = true;
+ }
+ LogDebug("Root CA for author signature is correct.");
+ } else {
+ if (!storeIdSet.contains(CertStoreId::DEVELOPER) &&
+ !storeIdSet.contains(CertStoreId::WAC_ROOT) &&
+ !storeIdSet.contains(CertStoreId::WAC_MEMBER))
+ {
+ LogWarning("Distiributor signature has got unrecognized Root CA "
+ "certificate. Signature will be disregarded.");
+ disregard = true;
+ } else {
+ LogDebug("Root CA for distributor signature is correct.");
+ }
+ }
+
+ data.setStorageType(storeIdSet);
+ data.setSortedCertificateList(sortedCertificateList);
+
+ // We add only Root CA certificate because WAC ensure that the rest
+ // of certificates are present in signature files ;-)
+ XmlSec::XmlSecContext context;
+ context.signatureFile = data.getSignatureFileName();
+ context.certificatePtr = root;
+
+ // Now we should have full certificate chain.
+ // If the end certificate is not ROOT CA we should disregard signature
+ // but still signature must be valid... Aaaaaa it's so stupid...
+ if (!(root->isSignedBy(root))) {
+ LogWarning("Root CA certificate not found. Chain is incomplete.");
+ context.allowBrokenChain = true;
+ }
+
+ // WAC 2.0 SP-2066 The wrt must not block widget installation
+ // due to expiration of the author certificate.
+ time_t notAfter = data.getEndEntityCertificatePtr()->getNotAfter();
+ bool expired = notAfter < time(NULL);
+ if (data.isAuthorSignature() && expired) {
+ context.validationTime = notAfter - TIMET_DAY;
+ }
+ // end
+
+ if (XmlSec::NO_ERROR != XmlSecSingleton::Instance().validate(&context)) {
+ LogWarning("Installation break - invalid package!");
+ return WrtSignatureValidator::SIGNATURE_INVALID;
+ }
+
+ data.setReference(context.referenceSet);
+
+ if (!checkObjectReferences(data)) {
+ return WrtSignatureValidator::SIGNATURE_INVALID;
+ }
+
+ ReferenceValidator fileValidator(widgetContentPath);
+ if (ReferenceValidator::NO_ERROR != fileValidator.checkReferences(data)) {
+ LogWarning("Invalid package - file references broken");
+ return WrtSignatureValidator::SIGNATURE_INVALID;
+ }
+
+ // It is good time to do OCSP check
+ // ocspCheck will throw an exception on any error.
+ // TODO Probably we should catch this exception and add
+ // some information to SignatureData.
+ if (!m_complianceModeEnabled && !data.isAuthorSignature()) {
+ CertificateCollection coll;
+ coll.load(sortedCertificateList);
+
+ if (!coll.sort()) {
+ LogDebug("Collection does not contain chain!");
+ return WrtSignatureValidator::SIGNATURE_INVALID;
+ }
+
+ CertificateVerifier verificator(m_ocspEnable, m_crlEnable);
+ VerificationStatus result = verificator.check(coll);
+
+ if (result == VERIFICATION_STATUS_REVOKED) {
+ return WrtSignatureValidator::SIGNATURE_REVOKED;
+ }
+
+ if (result == VERIFICATION_STATUS_UNKNOWN ||
+ result == VERIFICATION_STATUS_ERROR)
+ {
+ disregard = true;
+ }
+ }
+
+ if (disregard) {
+ LogWarning("Signature is disregard.");
+ return WrtSignatureValidator::SIGNATURE_DISREGARD;
+ }
+ return WrtSignatureValidator::SIGNATURE_VERIFIED;
+}
+
+// Implementation of WrtSignatureValidator
+
+WrtSignatureValidator::WrtSignatureValidator(
+ AppType appType,
+ bool ocspEnable,
+ bool crlEnable,
+ bool complianceMode)
+ : m_impl(0)
+{
+ if (appType == TIZEN)
+ m_impl = new ImplTizen(ocspEnable,crlEnable,complianceMode);
+ else
+ m_impl = new ImplWac(ocspEnable,crlEnable,complianceMode);
+}
+
+WrtSignatureValidator::~WrtSignatureValidator() {
+ delete m_impl;
+}
+
+WrtSignatureValidator::Result WrtSignatureValidator::check(
+ SignatureData &data,
+ const std::string &widgetContentPath)
+{
+ return m_impl->check(data, widgetContentPath);
+}
+
+} // namespace ValidationCore
+
--- /dev/null
+/*
+ * 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 WrtSignatureValidator.h
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief Implementatin of tizen signature validation protocol.
+ */
+#ifndef _VALIDATION_CORE_TIZENSIGNATUREVALIDATOR_H_
+#define _VALIDATION_CORE_TIZENSIGNATUREVALIDATOR_H_
+
+#include <string>
+
+#include <dpl/noncopyable.h>
+
+#include <vcore/SignatureData.h>
+
+namespace ValidationCore {
+
+class WrtSignatureValidator : public DPL::Noncopyable {
+public:
+ class Impl;
+
+ enum AppType
+ {
+ TIZEN,
+ WAC20
+ };
+
+ enum Result
+ {
+ SIGNATURE_VALID,
+ SIGNATURE_INVALID,
+ SIGNATURE_VERIFIED,
+ SIGNATURE_DISREGARD, // no ocsp response or ocsp return unknown status
+ SIGNATURE_REVOKED
+ };
+
+ explicit WrtSignatureValidator(
+ AppType appType,
+ bool ocspEnable,
+ bool crlEnable,
+ bool complianceMode);
+
+ virtual ~WrtSignatureValidator();
+
+ Result check(
+ SignatureData &data,
+ const std::string &widgetContentPath);
+
+private:
+ Impl *m_impl;
+};
+
+} // namespace ValidationCore
+
+#endif // _VALIDATION_CORE_TIZENSIGNATUREVALIDATOR_H_
+
--- /dev/null
+/*
+ * 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 XmlsecAdapter.cpp
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief
+ */
+#include <cstdlib>
+#include <cstring>
+
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+#ifndef XMLSEC_NO_XSLT
+#include <libxslt/xslt.h>
+#endif /* XMLSEC_NO_XSLT */
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/xmldsig.h>
+#include <xmlsec/crypto.h>
+#include <xmlsec/io.h>
+#include <xmlsec/keyinfo.h>
+
+#include <dpl/assert.h>
+#include <dpl/log/log.h>
+
+#include <vcore/XmlsecAdapter.h>
+
+#include <vcore/ValidatorCommon.h>
+
+#include <dpl/singleton_impl.h>
+IMPLEMENT_SINGLETON(ValidationCore::XmlSec)
+
+namespace {
+
+struct FileWrapper {
+ FileWrapper(void *argFile, bool argReleased)
+ : file(argFile)
+ , released(argReleased)
+ {}
+ void *file;
+ bool released;
+};
+
+} // anonymous namespace
+
+namespace ValidationCore {
+VC_DECLARE_DELETER(xmlSecKeysMngr, xmlSecKeysMngrDestroy)
+
+static const char* 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)
+{
+ std::string path = s_prefixPath + filename;
+ LogDebug("Xmlsec opening: " << path);
+ return new FileWrapper(xmlFileOpen(path.c_str()),false);
+}
+
+int XmlSec::fileReadCallback(void *context,
+ char *buffer,
+ int len)
+{
+ FileWrapper *fw = static_cast<FileWrapper*>(context);
+ if (fw->released) {
+ return 0;
+ }
+ int output = xmlFileRead(fw->file, buffer, len);
+ if (output == 0) {
+ fw->released = true;
+ xmlFileClose(fw->file);
+ }
+ return output;
+}
+
+int XmlSec::fileCloseCallback(void *context)
+{
+ FileWrapper *fw = static_cast<FileWrapper*>(context);
+ int output = 0;
+ if (!(fw->released)) {
+ output = xmlFileClose(fw->file);
+ }
+ delete fw;
+ return output;
+}
+
+void XmlSec::fileExtractPrefix(XmlSecContext *context)
+{
+ if (!(context->workingDirectory.empty())) {
+ s_prefixPath = context->workingDirectory;
+ return;
+ }
+
+ s_prefixPath = context->signatureFile;
+ size_t pos = s_prefixPath.rfind('/');
+ if (pos == std::string::npos) {
+ s_prefixPath.clear();
+ } else {
+ s_prefixPath.erase(pos + 1, std::string::npos);
+ }
+}
+
+XmlSec::XmlSec() :
+ m_initialized(false)
+{
+ LIBXML_TEST_VERSION
+ xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ xmlSubstituteEntitiesDefault(1);
+#ifndef XMLSEC_NO_XSLT
+ xmlIndentTreeOutput = 1;
+#endif
+
+ if (xmlSecInit() < 0) {
+ LogError("Xmlsec initialization failed.");
+ 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.");
+ }
+
+#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
+ if (xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
+ xmlSecShutdown();
+ LogError(
+ "Error: unable to load default xmlsec-crypto library. Make sure "
+ "that you have it installed and check shared libraries path "
+ "(LD_LIBRARY_PATH) envornment variable.");
+ ThrowMsg(Exception::InternalError,
+ "Unable to load default xmlsec-crypto library.");
+ }
+#endif
+
+ if (xmlSecCryptoAppInit(NULL) < 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.");
+ }
+
+ m_initialized = true;
+}
+
+void XmlSec::deinitialize(void)
+{
+ Assert(m_initialized);
+
+ /* 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 */
+
+ s_prefixPath.clear();
+ m_initialized = false;
+}
+
+XmlSec::~XmlSec()
+{
+ 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);
+
+ xmlSecIOCleanupCallbacks();
+
+ xmlSecIORegisterCallbacks(
+ fileMatchCallback,
+ fileOpenCallback,
+ 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;
+ }
+
+ /* find start node */
+ node = xmlSecFindNode(xmlDocGetRootElement(
+ doc), xmlSecNodeSignature, xmlSecDSigNs);
+ if (node == NULL) {
+ LogWarning("Start node not found in " << context->signatureFile);
+ goto done;
+ }
+
+ /* create signature context */
+ dsigCtx = xmlSecDSigCtxCreate(mngr);
+ if (dsigCtx == NULL) {
+ LogError("Failed to create signature context.");
+ goto done;
+ }
+
+ if (context->allowBrokenChain) {
+ dsigCtx->keyInfoReadCtx.flags |=
+ XMLSEC_KEYINFO_FLAGS_ALLOW_BROKEN_CHAIN;
+ }
+
+ if (context->validationTime) {
+ LogDebug("Setting validation time.");
+ dsigCtx->keyInfoReadCtx.certsVerificationTime = context->validationTime;
+ }
+
+ /* Verify signature */
+ if (xmlSecDSigCtxVerify(dsigCtx, node) < 0) {
+ LogWarning("Signature verify error.");
+ goto done;
+ }
+
+ 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;
+ }
+
+ /* print verification result to stdout */
+ if (dsigCtx->status == xmlSecDSigStatusSucceeded) {
+ LogDebug("Signature is OK");
+ res = 0;
+ } else {
+ LogDebug("Signature is INVALID");
+ goto done;
+ }
+
+ if (dsigCtx->c14nMethod && dsigCtx->c14nMethod->id &&
+ dsigCtx->c14nMethod->id->name) {
+ LogInfo("Canonicalization method: " <<
+ reinterpret_cast<const char *>(dsigCtx->c14nMethod->id->name));
+ }
+
+ 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<const char *>(dsigRefCtx->digestMethod->id
+ ->name);
+ std::string strDigest(pDigest);
+ LogInfo("reference digest method: " <<
+ reinterpret_cast<const char *>(dsigRefCtx->digestMethod
+ ->id
+ ->name));
+ if (strDigest == DIGEST_MD5) {
+ LogWarning("MD5 digest method used! Please use sha");
+ res = -1;
+ break;
+ }
+ }
+ context->referenceSet.insert(std::string(reinterpret_cast<char *>(
+ dsigRefCtx->uri)));
+ }
+ }
+
+done:
+ /* cleanup */
+ if (dsigCtx != NULL) {
+ xmlSecDSigCtxDestroy(dsigCtx);
+ }
+
+ if (doc != NULL) {
+ xmlFreeDoc(doc);
+ }
+
+ if (res) {
+ return ERROR_INVALID_SIGNATURE;
+ }
+ return NO_ERROR;
+}
+
+void XmlSec::loadDERCertificateMemory(XmlSecContext *context,
+ xmlSecKeysMngrPtr mngr)
+{
+ 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.");
+ }
+
+ if (xmlSecCryptoAppKeysMngrCertLoadMemory(mngr,
+ derCertificate,
+ size,
+ xmlSecKeyDataFormatDer,
+ xmlSecKeyDataTypeTrusted) < 0) {
+ OPENSSL_free(derCertificate);
+ LogError("Failed to load der certificate from memory.");
+ ThrowMsg(Exception::InternalError,
+ "Failed to load der certificate from memory.");
+ }
+
+ OPENSSL_free(derCertificate);
+}
+
+void XmlSec::loadPEMCertificateFile(XmlSecContext *context,
+ xmlSecKeysMngrPtr mngr)
+{
+ 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.");
+ }
+}
+
+XmlSec::Result XmlSec::validate(XmlSecContext *context)
+{
+ Assert(context);
+ Assert(!(context->signatureFile.empty()));
+ Assert(context->certificatePtr.Get() || !(context->certificatePath.empty()));
+
+ if (!m_initialized) {
+ LogError("XmlSec is not initialized.");
+ ThrowMsg(Exception::InternalError, "XmlSec is not initialized");
+ }
+
+ AutoPtr<xmlSecKeysMngr> mngr(xmlSecKeysMngrCreate());
+
+ if (!mngr.get()) {
+ LogError("Failed to create keys manager.");
+ ThrowMsg(Exception::InternalError, "Failed to create keys manager.");
+ }
+
+ if (xmlSecCryptoAppDefaultKeysMngrInit(mngr.get()) < 0) {
+ LogError("Failed to initialize keys manager.");
+ ThrowMsg(Exception::InternalError, "Failed to initialize keys manager.");
+ }
+ context->referenceSet.clear();
+
+ if (context->certificatePtr.Get()) {
+ loadDERCertificateMemory(context, mngr.get());
+ }
+
+ if (!context->certificatePath.empty()) {
+ loadPEMCertificateFile(context, mngr.get());
+ }
+
+ return validateFile(context, mngr.get());
+}
+} // namespace ValidationCore
--- /dev/null
+/*
+ * 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 XmlSecAdapter.h
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief
+ */
+#ifndef _VALIDATION_CORE_XMLSECADAPTER_H_
+#define _VALIDATION_CORE_XMLSECADAPTER_H_
+
+#include <xmlsec/keysmngr.h>
+
+#include <dpl/exception.h>
+#include <dpl/noncopyable.h>
+#include <dpl/singleton.h>
+
+#include <vcore/Certificate.h>
+#include <vcore/SignatureData.h>
+
+namespace ValidationCore {
+class XmlSec : public DPL::Noncopyable
+{
+ public:
+
+ struct XmlSecContext
+ {
+ /* You _must_ set one of the value: certificatePath or certificate. */
+ XmlSecContext() :
+ validationTime(0),
+ allowBrokenChain(false),
+ errorBrokenChain(false)
+ {
+ }
+
+ /*
+ * Absolute path to signature file.
+ */
+ std::string signatureFile;
+ /*
+ * Direcotory with signed data.
+ * If you leave it empty xmlsec will use directory extracted
+ * from signatureFile.
+ */
+ std::string workingDirectory;
+ /*
+ * Path to trusted certificate.
+ */
+ std::string certificatePath;
+ /*
+ * Trusted certificate. In most cases it should be Root CA certificate.
+ */
+ CertificatePtr certificatePtr;
+ /*
+ * Validation date.
+ * 0 - uses current time.
+ */
+ time_t validationTime;
+ /*
+ * Input parameter.
+ * If true, signature validation will not be interrupted by chain error.
+ * If true and chain is broken then the value errorBrokenChain will be
+ * set to true.
+ */
+ bool allowBrokenChain;
+ /*
+ * Output parameter.
+ * This will be set if chain is incomplete or broken.
+ */
+ bool errorBrokenChain;
+ /*
+ * Output parameter.
+ * Reference checked by xmlsec
+ */
+ ReferenceSet referenceSet;
+ };
+
+ enum Result
+ {
+ NO_ERROR,
+ ERROR_INVALID_SIGNATURE
+ };
+
+ class Exception
+ {
+ public:
+ DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
+ DECLARE_EXCEPTION_TYPE(Base, InternalError)
+ };
+
+ /*
+ * Context - input/output param.
+ */
+ Result validate(XmlSecContext *context);
+ 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);
+
+ bool m_initialized;
+
+ 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 int fileCloseCallback(void *context);
+ static void fileExtractPrefix(XmlSecContext *context);
+};
+
+typedef DPL::Singleton<XmlSec> XmlSecSingleton;
+
+} // namespace ValidationCore
+
+#endif // _VALIDATION_CORE_XMLSECVERIFICATOR_H_
--- /dev/null
+/**
+ * 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 api.cpp
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @author Jacek Migacz (j.migacz@samsung.com)
+ * @version 1.0
+ * @brief This is part of C-api proposition for cert-svc.
+ */
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <algorithm>
+#include <fstream>
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+#include <glib-object.h>
+
+#include <openssl/pem.h>
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+#include <openssl/pkcs12.h>
+#include <openssl/err.h>
+#include <openssl/sha.h>
+#include <openssl/evp.h>
+#include <openssl/bio.h>
+
+#include <dlog.h>
+
+#include <dpl/foreach.h>
+#include <dpl/log/log.h>
+
+#include <cert-svc/cinstance.h>
+#include <cert-svc/ccert.h>
+#include <cert-svc/cocsp.h>
+#include <cert-svc/cpkcs12.h>
+#include <cert-svc/ccrl.h>
+#include <cert-svc/cpkcs12.h>
+#include <cert-svc/cprimitives.h>
+
+#include <vcore/Base64.h>
+#include <vcore/Certificate.h>
+#include <vcore/CertificateCollection.h>
+#include <vcore/OCSP.h>
+#include <vcore/CRL.h>
+#include <vcore/CRLCacheInterface.h>
+#include <vcore/pkcs12.h>
+
+using namespace ValidationCore;
+
+namespace {
+
+typedef std::unique_ptr<CERT_CONTEXT, std::function<int(CERT_CONTEXT*)> > ScopedCertCtx;
+
+class CRLCacheCAPI : public CRLCacheInterface {
+public:
+ CRLCacheCAPI(
+ CertSvcCrlCacheWrite crlWrite,
+ CertSvcCrlCacheRead crlRead,
+ CertSvcCrlFree crlFree,
+ void *userParam)
+ : m_crlWrite(crlWrite)
+ , m_crlRead(crlRead)
+ , m_crlFree(crlFree)
+ , m_userParam(userParam)
+ {}
+
+ bool getCRLResponse(CRLCachedData *ptr){
+ if (!m_crlRead || !m_crlFree)
+ return false;
+
+ char *buffer;
+ int size;
+
+ bool result = m_crlRead(
+ ptr->distribution_point.c_str(),
+ &buffer,
+ &size,
+ &(ptr->next_update_time),
+ m_userParam);
+
+ if (result) {
+ ptr->crl_body.clear();
+ ptr->crl_body.append(buffer, size);
+ m_crlFree(buffer, m_userParam);
+ }
+
+ return result;
+ }
+ void setCRLResponse(CRLCachedData *ptr){
+ if (m_crlWrite) {
+ m_crlWrite(
+ ptr->distribution_point.c_str(),
+ ptr->crl_body.c_str(),
+ ptr->crl_body.size(),
+ ptr->next_update_time,
+ m_userParam);
+ }
+ }
+
+private:
+ CertSvcCrlCacheWrite m_crlWrite;
+ CertSvcCrlCacheRead m_crlRead;
+ CertSvcCrlFree m_crlFree;
+ void *m_userParam;
+};
+
+class CertSvcInstanceImpl {
+public:
+ CertSvcInstanceImpl()
+ : m_certificateCounter(0)
+ , m_idListCounter(0)
+ , m_stringListCounter(0)
+ , m_crlWrite(NULL)
+ , m_crlRead(NULL)
+ , m_crlFree(NULL)
+ {}
+
+ ~CertSvcInstanceImpl(){
+ FOREACH(it, m_allocatedStringSet) {
+ delete[] *it;
+ }
+ }
+
+ inline void reset(){
+ m_certificateCounter = 0;
+ m_certificateMap.clear();
+ m_idListCounter = 0;
+ m_idListMap.clear();
+ m_stringListCounter = 0;
+ m_stringListMap.clear();
+
+ FOREACH(it, m_allocatedStringSet) {
+ delete[] *it;
+ }
+
+ m_allocatedStringSet.clear();
+ }
+
+ inline int addCert(const CertificatePtr &cert) {
+ m_certificateMap[m_certificateCounter] = cert;
+ return m_certificateCounter++;
+ }
+
+ inline void removeCert(const CertSvcCertificate &cert) {
+ auto iter = m_certificateMap.find(cert.privateHandler);
+ if (iter != m_certificateMap.end()) {
+ m_certificateMap.erase(iter);
+ }
+ }
+
+ inline int getCertFromList(
+ const CertSvcCertificateList &handler,
+ int position,
+ CertSvcCertificate *certificate)
+ {
+ auto iter = m_idListMap.find(handler.privateHandler);
+ if (iter == m_idListMap.end()) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ if (position >= static_cast<int>(iter->second.size())) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ certificate->privateInstance = handler.privateInstance;
+ certificate->privateHandler = (iter->second)[position];
+ return CERTSVC_SUCCESS;
+ }
+
+ inline int getCertListLen(const CertSvcCertificateList &handler, int *len) {
+ auto iter = m_idListMap.find(handler.privateHandler);
+ if (iter == m_idListMap.end() || !len) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ *len = (iter->second).size();
+ return CERTSVC_SUCCESS;
+ }
+
+ inline void removeCertList(const CertSvcCertificateList &handler) {
+ auto iter = m_idListMap.find(handler.privateHandler);
+ if (iter != m_idListMap.end())
+ m_idListMap.erase(iter);
+ }
+
+ inline int isSignedBy(const CertSvcCertificate &child,
+ const CertSvcCertificate &parent,
+ int *status)
+ {
+ auto citer = m_certificateMap.find(child.privateHandler);
+ if (citer == m_certificateMap.end()) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ auto piter = m_certificateMap.find(parent.privateHandler);
+ if (piter == m_certificateMap.end()) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+
+ if (citer->second->isSignedBy(piter->second)) {
+ *status = CERTSVC_TRUE;
+ } else {
+ *status = CERTSVC_FALSE;
+ }
+ return CERTSVC_SUCCESS;
+ }
+
+ inline int getField(const CertSvcCertificate &cert,
+ CertSvcCertificateField field,
+ CertSvcString *buffer)
+ {
+ auto iter = m_certificateMap.find(cert.privateHandler);
+ if (iter == m_certificateMap.end()) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+
+ auto certPtr = iter->second;
+ DPL::OptionalString result;
+ switch(field) {
+ case CERTSVC_SUBJECT:
+ result = DPL::OptionalString(certPtr->getOneLine());
+ break;
+ case CERTSVC_ISSUER:
+ result = DPL::OptionalString(certPtr->getOneLine(Certificate::FIELD_ISSUER));
+ break;
+ case CERTSVC_SUBJECT_COMMON_NAME:
+ result = certPtr->getCommonName();
+ break;
+ case CERTSVC_SUBJECT_COUNTRY_NAME:
+ result = certPtr->getCountryName();
+ break;
+ case CERTSVC_SUBJECT_STATE_NAME:
+ result = certPtr->getStateOrProvinceName();
+ break;
+ case CERTSVC_SUBJECT_ORGANIZATION_NAME:
+ result = certPtr->getOrganizationName();
+ break;
+ case CERTSVC_SUBJECT_ORGANIZATION_UNIT_NAME:
+ result = certPtr->getOrganizationalUnitName();
+ break;
+ case CERTSVC_SUBJECT_EMAIL_ADDRESS:
+ result = certPtr->getEmailAddres();
+ break;
+ case CERTSVC_ISSUER_COMMON_NAME:
+ result = certPtr->getCommonName(Certificate::FIELD_ISSUER);
+ break;
+ case CERTSVC_ISSUER_STATE_NAME:
+ result = certPtr->getStateOrProvinceName(Certificate::FIELD_ISSUER);
+ break;
+ case CERTSVC_ISSUER_ORGANIZATION_NAME:
+ result = certPtr->getOrganizationName(Certificate::FIELD_ISSUER);
+ break;
+ case CERTSVC_ISSUER_ORGANIZATION_UNIT_NAME:
+ result = certPtr->getOrganizationalUnitName(Certificate::FIELD_ISSUER);
+ break;
+ case CERTSVC_VERSION:
+ {
+ std::stringstream stream;
+ stream << (certPtr->getVersion()+1);
+ result = DPL::OptionalString(DPL::FromUTF8String(stream.str()));
+ break;
+ }
+ case CERTSVC_SERIAL_NUMBER:
+ result = DPL::OptionalString(certPtr->getSerialNumberString());
+ break;
+ case CERTSVC_KEY_USAGE:
+ result = DPL::OptionalString(certPtr->getKeyUsageString());
+ break;
+ case CERTSVC_KEY:
+ result = DPL::OptionalString(certPtr->getPublicKeyString());
+ break;
+ case CERTSVC_SIGNATURE_ALGORITHM:
+ result = DPL::OptionalString(certPtr->getSignatureAlgorithmString());
+ break;
+ default:
+ break;
+ }
+
+ if (result.IsNull()) {
+ buffer->privateHandler = NULL;
+ buffer->privateLength = 0;
+ buffer->privateInstance = cert.privateInstance;
+ return CERTSVC_SUCCESS;
+ }
+ std::string output = DPL::ToUTF8String(*result);
+
+ char *cstring = new char[output.size()+1];
+ strncpy(cstring, output.c_str(), output.size()+1);
+
+ buffer->privateHandler = cstring;
+ buffer->privateLength = output.size();
+ buffer->privateInstance = cert.privateInstance;
+
+ m_allocatedStringSet.insert(cstring);
+
+ return CERTSVC_SUCCESS;
+ }
+
+ inline int getNotAfter(const CertSvcCertificate &cert,
+ time_t *time)
+ {
+ auto iter = m_certificateMap.find(cert.privateHandler);
+ if (iter == m_certificateMap.end()) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ *time = iter->second->getNotAfter();
+ return CERTSVC_SUCCESS;
+ }
+
+ inline int getNotBefore(const CertSvcCertificate &cert,
+ time_t *time)
+ {
+ auto iter = m_certificateMap.find(cert.privateHandler);
+ if (iter == m_certificateMap.end()) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ *time = iter->second->getNotBefore();
+ return CERTSVC_SUCCESS;
+ }
+
+ inline int isRootCA(const CertSvcCertificate &cert, int *status){
+ auto iter = m_certificateMap.find(cert.privateHandler);
+ if (iter == m_certificateMap.end()) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ if (iter->second->isRootCert()) {
+ *status = CERTSVC_TRUE;
+ } else {
+ *status = CERTSVC_FALSE;
+ }
+ return CERTSVC_SUCCESS;
+ }
+
+ inline int getCrl(const CertSvcCertificate &cert, CertSvcStringList *handler){
+ auto iter = m_certificateMap.find(cert.privateHandler);
+ if (iter == m_certificateMap.end()) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ int position = m_stringListCounter++;
+
+ std::list<std::string> temp = iter->second->getCrlUris();
+ std::copy(temp.begin(),
+ temp.end(),
+ back_inserter(m_stringListMap[position]));
+
+ handler->privateHandler = position;
+ handler->privateInstance = cert.privateInstance;
+
+ return CERTSVC_SUCCESS;
+ }
+
+ inline int getStringFromList(
+ const CertSvcStringList &handler,
+ int position,
+ CertSvcString *buffer)
+ {
+ buffer->privateHandler = NULL;
+ buffer->privateLength = 0;
+
+ auto iter = m_stringListMap.find(handler.privateHandler);
+ if (iter == m_stringListMap.end()) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ if (position >= (int)iter->second.size()) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ const std::string &data = iter->second.at(position);
+ int size = data.size();
+ char *cstring = new char[size+1];
+ if (!cstring) {
+ return CERTSVC_FAIL;
+ }
+
+ strncpy(cstring, data.c_str(), data.size()+1);
+
+ buffer->privateHandler = cstring;
+ buffer->privateLength = data.size();
+ buffer->privateInstance = handler.privateInstance;
+
+ m_allocatedStringSet.insert(cstring);
+
+ return CERTSVC_SUCCESS;
+ }
+
+ inline int getStringListLen(
+ const CertSvcStringList &handler,
+ int *size)
+ {
+ auto iter = m_stringListMap.find(handler.privateHandler);
+ if (iter == m_stringListMap.end()) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ *size = (int) iter->second.size();
+ return CERTSVC_SUCCESS;
+ }
+
+ inline void removeStringList(const CertSvcStringList &handler)
+ {
+ m_stringListMap.erase(m_stringListMap.find(handler.privateHandler));
+ }
+
+ inline void removeString(const CertSvcString &handler)
+ {
+ auto iter = m_allocatedStringSet.find(handler.privateHandler);
+ if (iter != m_allocatedStringSet.end()) {
+ delete[] *iter;
+ m_allocatedStringSet.erase(iter);
+ }
+ }
+
+ inline int certificateSearch(
+ CertSvcInstance instance,
+ CertSvcCertificateField field,
+ const char *value,
+ CertSvcCertificateList *handler)
+ {
+ int result;
+ search_field fieldId = SEARCH_FIELD_END;
+
+ switch(field){
+ case CERTSVC_SUBJECT:
+ fieldId = SUBJECT_STR;
+ break;
+ case CERTSVC_ISSUER:
+ fieldId = ISSUER_STR;
+ break;
+ case CERTSVC_SUBJECT_COMMON_NAME:
+ fieldId = SUBJECT_COMMONNAME;
+ break;
+ default:
+ LogError("Not implemented!");
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+
+ ScopedCertCtx ctx(cert_svc_cert_context_init(),
+ cert_svc_cert_context_final);
+
+ if (ctx.get() == NULL) {
+ LogWarning("Error in cert_svc_cert_context_init.");
+ return CERTSVC_FAIL;
+ }
+
+ LogDebug("Match string: " << value);
+ result = cert_svc_search_certificate(ctx.get(), fieldId, const_cast<char*>(value));
+ LogDebug("Search finished!");
+
+ if (CERT_SVC_ERR_NO_ERROR != result) {
+ LogWarning("Error during certificate search");
+ return CERTSVC_FAIL;
+ }
+
+ cert_svc_filename_list *fileList = ctx.get()->fileNames;
+
+ int listId = m_idListCounter++;
+ std::vector<int> &list = m_idListMap[listId];
+ handler->privateHandler = listId;
+ handler->privateInstance = instance;
+
+ for(;fileList != NULL; fileList = fileList->next) {
+ ScopedCertCtx ctx2(cert_svc_cert_context_init(),
+ cert_svc_cert_context_final);
+ if (ctx2.get() == NULL) {
+ LogWarning("Error in cert_svc_cert_context_init.");
+ return CERTSVC_FAIL;
+ }
+
+ // TODO add read_certifcate_from_file function to Certificate.h
+ if (CERT_SVC_ERR_NO_ERROR !=
+ cert_svc_load_file_to_context(ctx2.get(), fileList->filename))
+ {
+ LogWarning("Error in cert_svc_load_file_to_context");
+ return CERTSVC_FAIL;
+ }
+ int certId = addCert(CertificatePtr(new Certificate(*(ctx2.get()->certBuf))));
+ list.push_back(certId);
+ }
+ return CERTSVC_SUCCESS;
+ }
+
+ inline int sortCollection(CertSvcCertificate *certificate_array, int size) {
+ if (size < 2) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+
+ for(int i=1; i<size; ++i) {
+ if (certificate_array[i-1].privateInstance.privatePtr
+ != certificate_array[i].privateInstance.privatePtr)
+ {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ }
+
+ CertificateList certList;
+ std::map<Certificate*,int> translator;
+
+ for(int i=0; i<size; ++i) {
+ int pos = certificate_array[i].privateHandler;
+ auto cert = m_certificateMap.find(pos);
+ if (cert == m_certificateMap.end()) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ translator[cert->second.Get()] = pos;
+ certList.push_back(cert->second);
+ }
+
+ CertificateCollection collection;
+ collection.load(certList);
+
+ if (!collection.sort()) {
+ return CERTSVC_FAIL;
+ }
+
+ auto chain = collection.getChain();
+
+ int i=0;
+ for (auto iter = chain.begin(); iter != chain.end() && i<size; ++iter, ++i) {
+ certificate_array[i].privateHandler = translator[iter->Get()];
+ }
+
+ return CERTSVC_SUCCESS;
+ }
+
+ inline int getX509Copy(const CertSvcCertificate &certificate, X509** cert)
+ {
+ auto it = m_certificateMap.find(certificate.privateHandler);
+ if (it == m_certificateMap.end()) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ *cert = X509_dup(it->second->getX509());
+ return CERTSVC_SUCCESS;
+ }
+
+ inline int saveToFile(const CertSvcCertificate &certificate,
+ const char *location)
+ {
+ auto it = m_certificateMap.find(certificate.privateHandler);
+ if (it == m_certificateMap.end()) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ FILE *out;
+ if (NULL == (out = fopen(location, "w"))) {
+ return CERTSVC_FAIL;
+ }
+ if (0 == i2d_X509_fp(out, it->second->getX509())) {
+ fclose(out);
+ return CERTSVC_FAIL;
+ }
+ fclose(out);
+ return CERTSVC_SUCCESS;
+ }
+
+ inline int ocspCheck(const CertSvcCertificate *chain,
+ int chain_size,
+ const CertSvcCertificate *trusted,
+ int trusted_size,
+ const char *url,
+ int *status)
+ {
+ auto instance = chain[0].privateInstance.privatePtr;
+
+ for(int i=1; i<chain_size; ++i) {
+ if (instance != chain[i].privateInstance.privatePtr)
+ {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ }
+ CertificateList chainList, trustedList;
+
+ for(int i=0; i<chain_size; ++i) {
+ auto cert = m_certificateMap.find(chain[i].privateHandler);
+ if (cert == m_certificateMap.end()) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ chainList.push_back(cert->second);
+ }
+
+ for(int i=0; i<trusted_size; ++i) {
+ if (instance != trusted[i].privateInstance.privatePtr)
+ {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ }
+
+ for(int i=0; i<trusted_size; ++i) {
+ auto cert = m_certificateMap.find(trusted[i].privateHandler);
+ if (cert == m_certificateMap.end()) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ trustedList.push_back(cert->second);
+ }
+
+ OCSP ocsp;
+// ocsp.setDigestAlgorithmForCertId(OCSP::SHA1);
+// ocsp.setDigestAlgorithmForRequest(OCSP::SHA1);
+ ocsp.setTrustedStore(trustedList);
+
+ if (url) {
+ ocsp.setUseDefaultResponder(true);
+ ocsp.setDefaultResponder(url);
+ }
+
+ CertificateCollection collection;
+ collection.load(chainList);
+ if (!collection.sort()) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+
+ chainList = collection.getChain();
+
+ VerificationStatusSet statusSet = ocsp.validateCertificateList(chainList);
+
+ int ret = 0;
+ if (statusSet.contains(VERIFICATION_STATUS_GOOD)) {
+ ret |= CERTSVC_OCSP_GOOD;
+ }
+ if (statusSet.contains(VERIFICATION_STATUS_REVOKED)) {
+ ret |= CERTSVC_OCSP_REVOKED;
+ }
+ if (statusSet.contains(VERIFICATION_STATUS_UNKNOWN)) {
+ ret |= CERTSVC_OCSP_UNKNOWN;
+ }
+ if (statusSet.contains(VERIFICATION_STATUS_VERIFICATION_ERROR)) {
+ ret |= CERTSVC_OCSP_VERIFICATION_ERROR;
+ }
+ if (statusSet.contains(VERIFICATION_STATUS_NOT_SUPPORT)) {
+ ret |= CERTSVC_OCSP_NO_SUPPORT;
+ }
+ if (statusSet.contains(VERIFICATION_STATUS_ERROR)) {
+ ret |= CERTSVC_OCSP_ERROR;
+ }
+
+ *status = ret;
+ return CERTSVC_SUCCESS;
+ }
+
+ inline int verify(
+ CertSvcCertificate certificate,
+ CertSvcString &message,
+ CertSvcString &signature,
+ const char *algorithm,
+ int *status)
+ {
+ int result = CERTSVC_FAIL;
+
+ if (!status) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+
+ auto it = m_certificateMap.find(certificate.privateHandler);
+ if (it == m_certificateMap.end()) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+
+ OpenSSL_add_all_digests();
+
+ int temp;
+ EVP_MD_CTX* mdctx = NULL;
+ const EVP_MD * md = NULL;
+ X509 *cert = it->second->getX509();
+ EVP_PKEY *pkey = NULL;
+
+ if (cert == NULL) {
+ goto err;
+ }
+
+ pkey = X509_get_pubkey(cert);
+
+ if (pkey == NULL) {
+ goto err;
+ }
+
+ if (algorithm == NULL) {
+ md = EVP_get_digestbyobj(cert->cert_info->signature->algorithm);
+ } else {
+ md = EVP_get_digestbyname(algorithm);
+ }
+
+ if (md == NULL) {
+ result = CERTSVC_INVALID_ALGORITHM;
+ goto err;
+ }
+
+ mdctx = EVP_MD_CTX_create();
+
+ if (mdctx == NULL) {
+ goto err;
+ }
+
+ if (EVP_VerifyInit_ex(mdctx, md, NULL) != 1) {
+ goto err;
+ }
+
+ if (EVP_VerifyUpdate(mdctx, message.privateHandler, message.privateLength) != 1) {
+ goto err;
+ }
+
+ temp = EVP_VerifyFinal(mdctx,
+ reinterpret_cast<unsigned char*>(signature.privateHandler),
+ signature.privateLength,
+ pkey);
+
+ if (temp == 0) {
+ *status = CERTSVC_INVALID_SIGNATURE;
+ result = CERTSVC_SUCCESS;
+ } else if (temp == 1) {
+ *status = CERTSVC_SUCCESS;
+ result = CERTSVC_SUCCESS;
+ }
+
+ err:
+ if (mdctx != NULL)
+ EVP_MD_CTX_destroy(mdctx);
+ if (pkey != NULL)
+ EVP_PKEY_free(pkey);
+ return result;
+ }
+
+ inline int base64Encode(
+ const CertSvcString &message,
+ CertSvcString *base64)
+ {
+ if (!base64) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ std::string info(message.privateHandler, message.privateLength);
+ Base64Encoder base;
+ base.reset();
+ base.append(info);
+ base.finalize();
+ info = base.get();
+ char *ptr = new char[info.size()+1];
+ memcpy(ptr, info.c_str(), info.size()+1);
+ m_allocatedStringSet.insert(ptr);
+ base64->privateHandler = ptr;
+ base64->privateLength = info.size();
+ base64->privateInstance = message.privateInstance;
+ return CERTSVC_SUCCESS;
+ }
+
+ int base64Decode(
+ const CertSvcString &base64,
+ CertSvcString *message)
+ {
+ if (!message) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ std::string info(base64.privateHandler, base64.privateLength);
+ Base64Decoder base;
+ base.reset();
+ base.append(info);
+ if (!base.finalize()) {
+ return CERTSVC_FAIL;
+ }
+ info = base.get();
+ char *ptr = new char[info.size()+1];
+ memcpy(ptr, info.c_str(), info.size()+1);
+ m_allocatedStringSet.insert(ptr);
+ message->privateHandler = ptr;
+ message->privateLength = info.size();
+ message->privateInstance = base64.privateInstance;
+ return CERTSVC_SUCCESS;
+ }
+
+ inline int stringNew(
+ CertSvcInstance &instance,
+ const char *str,
+ int size,
+ CertSvcString *output)
+ {
+ if (!output || size < 0) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+
+ int allocSize = size;
+
+ if (allocSize == 0 || str[allocSize-1] != 0)
+ allocSize++;
+
+ char *ptr = new char[allocSize];
+ memcpy(ptr, str, size);
+ ptr[allocSize-1] = 0;
+
+ output->privateHandler = ptr;
+ output->privateLength = size;
+ output->privateInstance = instance;
+
+ m_allocatedStringSet.insert(ptr);
+
+ return CERTSVC_SUCCESS;
+ }
+
+ inline void setCRLFunction(
+ CertSvcCrlCacheWrite writePtr,
+ CertSvcCrlCacheRead readPtr,
+ CertSvcCrlFree freePtr)
+ {
+ m_crlWrite = writePtr;
+ m_crlRead = readPtr;
+ m_crlFree = freePtr;
+ }
+
+ inline int crlCheck(
+ CertSvcCertificate certificate,
+ CertSvcCertificate *trustedStore,
+ int storeSize,
+ int force,
+ int *status,
+ void *userParam)
+ {
+ for(int i=1; i<storeSize; ++i) {
+ if (certificate.privateInstance.privatePtr
+ != trustedStore[i].privateInstance.privatePtr)
+ {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ }
+
+ CRL crl(new CRLCacheCAPI(m_crlWrite, m_crlRead, m_crlFree, userParam));
+
+ for (int i=0; i<storeSize; ++i) {
+ auto iter = m_certificateMap.find(trustedStore[i].privateHandler);
+ if (iter == m_certificateMap.end()) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ crl.addToStore(iter->second);
+ }
+
+ auto iter = m_certificateMap.find(certificate.privateHandler);
+ if (iter == m_certificateMap.end()) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ if (iter->second->getCrlUris().empty()) {
+ *status = CERTSVC_CRL_NO_SUPPORT;
+ return CERTSVC_SUCCESS;
+ }
+ crl.updateList(iter->second, force ? CRL::UPDATE_ON_DEMAND: CRL::UPDATE_ON_EXPIRED);
+ CRL::RevocationStatus st = crl.checkCertificate(iter->second);
+ *status = 0;
+
+ if (!st.isCRLValid) {
+ *status |= CERTSVC_CRL_VERIFICATION_ERROR;
+ return CERTSVC_SUCCESS;
+ }
+
+ if (st.isRevoked) {
+ *status |= CERTSVC_CRL_REVOKED;
+ } else {
+ *status |= CERTSVC_CRL_GOOD;
+ }
+
+ return CERTSVC_SUCCESS;
+ }
+
+ inline int certificateVerify(
+ CertSvcCertificate certificate,
+ CertSvcCertificate *trusted,
+ int trustedSize,
+ CertSvcCertificate *untrusted,
+ int untrustedSize,
+ int *status)
+ {
+ if (!trusted || !status) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ auto iter = m_certificateMap.find(certificate.privateHandler);
+ if (iter == m_certificateMap.end()) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+
+ X509 *cert = iter->second->getX509();
+ X509_STORE *store = X509_STORE_new();
+ STACK_OF(X509) *ustore = sk_X509_new_null();
+
+ for (int i=0; i<trustedSize; ++i) {
+ auto iter = m_certificateMap.find(trusted[i].privateHandler);
+ if (iter == m_certificateMap.end()) {
+ X509_STORE_free(store);
+ sk_X509_free(ustore);
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ X509_STORE_add_cert(store, iter->second->getX509());
+ }
+
+ for (int i=0; i<untrustedSize; ++i) {
+ auto iter = m_certificateMap.find(untrusted[i].privateHandler);
+ if (iter == m_certificateMap.end()) {
+ X509_STORE_free(store);
+ sk_X509_free(ustore);
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ sk_X509_push(ustore, iter->second->getX509());
+ }
+ X509_STORE_CTX context;
+ X509_STORE_CTX_init(&context, store, cert, ustore);
+ int result = X509_verify_cert(&context);
+ X509_STORE_CTX_cleanup(&context);
+ X509_STORE_free(store);
+ sk_X509_free(ustore);
+
+ if (result == 1) {
+ *status = CERTSVC_SUCCESS;
+ } else {
+ *status = CERTSVC_FAIL;
+ }
+ return CERTSVC_SUCCESS;
+ }
+
+ inline int pkcsNameIsUnique(
+ CertSvcString pfxIdString,
+ int *is_unique)
+ {
+ gboolean exists;
+ int result = c_certsvc_pkcs12_alias_exists(pfxIdString.privateHandler, &exists);
+ *is_unique = !exists;
+ return result;
+ }
+
+ inline int pkcsImport(
+ CertSvcString path,
+ CertSvcString pass,
+ CertSvcString pfxIdString)
+ {
+ return c_certsvc_pkcs12_import(path.privateHandler, pass.privateHandler, pfxIdString.privateHandler);
+ }
+
+ inline int getPkcsIdList(
+ CertSvcInstance &instance,
+ CertSvcStringList *handler)
+ {
+ gchar **aliases;
+ gsize i, naliases;
+ std::vector<std::string> output;
+ int result;
+
+ result = c_certsvc_pkcs12_aliases_load(&aliases, &naliases);
+ if(result != CERTSVC_SUCCESS)
+ return result;
+ for(i = 0; i < naliases; i++)
+ output.push_back(std::string(aliases[i]));
+ c_certsvc_pkcs12_aliases_free(aliases);
+
+ int position = m_stringListCounter++;
+ m_stringListMap[position] = output;
+
+ handler->privateHandler = position;
+ handler->privateInstance = instance;
+ return CERTSVC_SUCCESS;
+ }
+
+ inline int pkcsHasPassword(
+ CertSvcString filepath,
+ int *has_password)
+ {
+ return c_certsvc_pkcs12_has_password(filepath.privateHandler, has_password);
+ }
+
+ inline int getPkcsPrivateKey(
+ CertSvcString pfxIdString,
+ char **buffer,
+ size_t *size)
+ {
+ return c_certsvc_pkcs12_private_key_load(pfxIdString.privateHandler, buffer, size);
+ }
+
+ inline int getPkcsCertificateList(
+ CertSvcInstance &instance,
+ CertSvcString &pfxIdString,
+ CertSvcCertificateList *handler)
+ {
+ gchar **certs;
+ gsize i, ncerts;
+ std::vector<CertificatePtr> certPtrVector;
+ std::vector<int> listId;
+ int result;
+
+ result = c_certsvc_pkcs12_load_certificates(pfxIdString.privateHandler, &certs, &ncerts);
+ if(result != CERTSVC_SUCCESS)
+ return result;
+ for(i = 0; i < ncerts; i++) {
+ ScopedCertCtx context(cert_svc_cert_context_init(), cert_svc_cert_context_final);
+ if(cert_svc_load_file_to_context(context.get(), certs[i]) != CERT_SVC_ERR_NO_ERROR) {
+ c_certsvc_pkcs12_free_certificates(certs);
+ return CERTSVC_IO_ERROR;
+ }
+ else
+ certPtrVector.push_back(CertificatePtr(new Certificate(*(context->certBuf))));
+ }
+ if(ncerts > 0)
+ c_certsvc_pkcs12_free_certificates(certs);
+
+ FOREACH(it, certPtrVector) {
+ listId.push_back(addCert(*it));
+ }
+
+ int position = m_idListCounter++;
+ m_idListMap[position] = listId;
+
+ handler->privateInstance = instance;
+ handler->privateHandler = position;
+
+ return result;
+ }
+
+ inline int pkcsDelete(CertSvcString pfxIdString)
+ {
+ return c_certsvc_pkcs12_delete(pfxIdString.privateHandler);
+ }
+
+private:
+ int m_certificateCounter;
+ std::map<int, CertificatePtr> m_certificateMap;
+
+ int m_idListCounter;
+ std::map<int, std::vector<int> > m_idListMap;
+
+ int m_stringListCounter;
+ std::map<int, std::vector<std::string> > m_stringListMap;
+
+ std::set<char *> m_allocatedStringSet;
+
+ CertSvcCrlCacheWrite m_crlWrite;
+ CertSvcCrlCacheRead m_crlRead;
+ CertSvcCrlFree m_crlFree;
+};
+
+inline CertSvcInstanceImpl *impl(CertSvcInstance instance) {
+ return static_cast<CertSvcInstanceImpl*>(instance.privatePtr);
+}
+
+} // namespace anonymous
+
+int certsvc_instance_new(CertSvcInstance *instance) {
+ static int init = 1;
+ if (init) {
+ SSL_library_init(); // required by message verification
+ OpenSSL_add_all_digests();
+ g_type_init(); // required by libsoup/ocsp
+ init = 0;
+ }
+ try {
+ instance->privatePtr =
+ reinterpret_cast<void*>(new CertSvcInstanceImpl);
+ if (instance->privatePtr)
+ return CERTSVC_SUCCESS;
+ } catch (std::bad_alloc &) {
+ return CERTSVC_BAD_ALLOC;
+ } catch (...) {}
+ return CERTSVC_FAIL;
+}
+
+void certsvc_instance_reset(CertSvcInstance instance) {
+ impl(instance)->reset();
+}
+
+void certsvc_instance_free(CertSvcInstance instance) {
+ delete impl(instance);
+}
+
+int certsvc_certificate_new_from_file(
+ CertSvcInstance instance,
+ const char *location,
+ CertSvcCertificate *certificate)
+{
+ try {
+ ScopedCertCtx context(cert_svc_cert_context_init(),
+ cert_svc_cert_context_final);
+
+ int result = cert_svc_load_file_to_context(context.get(), location);
+
+ switch(result) {
+ case CERT_SVC_ERR_INVALID_PARAMETER: return CERTSVC_WRONG_ARGUMENT;
+ case CERT_SVC_ERR_INVALID_OPERATION: return CERTSVC_FAIL;
+ case CERT_SVC_ERR_MEMORY_ALLOCATION: return CERTSVC_BAD_ALLOC;
+ default:;
+ }
+
+ CertificatePtr cert(new Certificate(*(context->certBuf)));
+
+ certificate->privateInstance = instance;
+ certificate->privateHandler = impl(instance)->addCert(cert);
+
+ return CERTSVC_SUCCESS;
+ // TODO support for std exceptions
+ } catch (std::bad_alloc &) {
+ return CERTSVC_BAD_ALLOC;
+ } catch (...) {}
+ return CERTSVC_FAIL;
+}
+
+int certsvc_certificate_new_from_memory(
+ CertSvcInstance instance,
+ const unsigned char *memory,
+ int len,
+ CertSvcCertificateForm form,
+ CertSvcCertificate *certificate)
+{
+ try {
+ Certificate::FormType formType;
+ std::string binary((char*)memory, len);
+
+ if (CERTSVC_FORM_DER == form) {
+ formType = Certificate::FORM_DER;
+ } else {
+ formType = Certificate::FORM_BASE64;
+ }
+
+ CertificatePtr cert(new Certificate(binary, formType));
+
+ certificate->privateInstance = instance;
+ certificate->privateHandler = impl(instance)->addCert(cert);
+ return CERTSVC_SUCCESS;
+ } catch (std::bad_alloc &) {
+ return CERTSVC_BAD_ALLOC;
+ } catch (...) {}
+ return CERTSVC_FAIL;
+}
+
+void certsvc_certificate_free(CertSvcCertificate certificate)
+{
+ impl(certificate.privateInstance)->removeCert(certificate);
+}
+
+int certsvc_certificate_save_file(
+ CertSvcCertificate certificate,
+ const char *location)
+{
+ return impl(certificate.privateInstance)->saveToFile(certificate, location);
+}
+
+int certsvc_certificate_search(
+ CertSvcInstance instance,
+ CertSvcCertificateField field,
+ const char *value,
+ CertSvcCertificateList *handler)
+{
+ try {
+ return impl(instance)->certificateSearch(instance, field, value, handler);
+ } catch (std::bad_alloc &) {
+ return CERTSVC_BAD_ALLOC;
+ } catch (...) {}
+ return CERTSVC_FAIL;
+}
+
+int certsvc_certificate_list_get_one(
+ CertSvcCertificateList handler,
+ int position,
+ CertSvcCertificate *certificate)
+{
+ return impl(handler.privateInstance)->
+ getCertFromList(handler,position, certificate);
+}
+
+int certsvc_certificate_list_get_length(
+ CertSvcCertificateList handler,
+ int *size)
+{
+ return impl(handler.privateInstance)->getCertListLen(handler, size);
+}
+
+void certsvc_certificate_list_free(CertSvcCertificateList handler)
+{
+ impl(handler.privateInstance)->removeCertList(handler);
+}
+
+int certsvc_certificate_is_signed_by(
+ CertSvcCertificate child,
+ CertSvcCertificate parent,
+ int *status)
+{
+ if (child.privateInstance.privatePtr == parent.privateInstance.privatePtr) {
+ return impl(child.privateInstance)->isSignedBy(child, parent, status);
+ }
+ return CERTSVC_WRONG_ARGUMENT;
+}
+
+int certsvc_certificate_get_string_field(
+ CertSvcCertificate certificate,
+ CertSvcCertificateField field,
+ CertSvcString *buffer)
+{
+ try {
+ return impl(certificate.privateInstance)->getField(certificate, field, buffer);
+ } catch (std::bad_alloc &) {
+ return CERTSVC_BAD_ALLOC;
+ } catch (...) {}
+ return CERTSVC_FAIL;
+}
+
+int certsvc_certificate_get_not_after(
+ CertSvcCertificate certificate,
+ time_t *result)
+{
+ try {
+ return impl(certificate.privateInstance)->getNotAfter(certificate, result);
+ } catch(...) {}
+ return CERTSVC_FAIL;
+}
+
+int certsvc_certificate_get_not_before(
+ CertSvcCertificate certificate,
+ time_t *result)
+{
+ try {
+ return impl(certificate.privateInstance)->getNotBefore(certificate, result);
+ } catch(...) {}
+ return CERTSVC_FAIL;
+}
+
+int certsvc_certificate_is_root_ca(CertSvcCertificate certificate, int *status)
+{
+ return impl(certificate.privateInstance)->isRootCA(certificate, status);
+}
+
+int certsvc_certificate_get_crl_distribution_points(
+ CertSvcCertificate certificate,
+ CertSvcStringList *handler)
+{
+ try {
+ return impl(certificate.privateInstance)->getCrl(certificate, handler);
+ } catch (...) {}
+ return CERTSVC_FAIL;
+}
+
+int certsvc_string_list_get_one(
+ CertSvcStringList handler,
+ int position,
+ CertSvcString *buffer)
+{
+ try {
+ return impl(handler.privateInstance)->getStringFromList(handler, position, buffer);
+ } catch (std::bad_alloc &) {
+ return CERTSVC_BAD_ALLOC;
+ } catch (...) {}
+ return CERTSVC_FAIL;
+}
+
+int certsvc_string_list_get_length(
+ CertSvcStringList handler,
+ int *size)
+{
+ return impl(handler.privateInstance)->getStringListLen(handler, size);
+}
+
+void certsvc_string_list_free(CertSvcStringList handler)
+{
+ impl(handler.privateInstance)->removeStringList(handler);
+}
+
+void certsvc_string_free(CertSvcString string)
+{
+ impl(string.privateInstance)->removeString(string);
+}
+
+void certsvc_string_to_cstring(
+ CertSvcString string,
+ const char **buffer,
+ int *len)
+{
+ if (buffer) {
+ *buffer = string.privateHandler;
+ }
+ if (len) {
+ *len = string.privateLength;
+ }
+}
+
+int certsvc_certificate_chain_sort(
+ CertSvcCertificate *certificate_array,
+ int size)
+{
+ try {
+ if (!certificate_array) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ return impl(certificate_array[0].privateInstance)->
+ sortCollection(certificate_array, size);
+ } catch (std::bad_alloc &) {
+ return CERTSVC_BAD_ALLOC;
+ } catch (...) {}
+ return CERTSVC_FAIL;
+}
+
+int certsvc_certificate_dup_x509(CertSvcCertificate certificate, X509 **cert)
+{
+ try {
+ return impl(certificate.privateInstance)->getX509Copy(certificate, cert);
+ } catch (...) {}
+ return CERTSVC_FAIL;
+}
+
+void certsvc_certificate_free_x509(X509 *x509)
+{
+ X509_free(x509);
+}
+
+int certsvc_pkcs12_dup_evp_pkey(
+ CertSvcInstance instance,
+ CertSvcString alias,
+ EVP_PKEY** pkey)
+{
+ char *buffer;
+ size_t size;
+
+ int result = certsvc_pkcs12_private_key_dup(
+ instance,
+ alias,
+ &buffer,
+ &size);
+
+ if (result != CERTSVC_SUCCESS) {
+ LogError("Error in certsvc_pkcs12_private_key_dup");
+ return result;
+ }
+
+ BIO *b = BIO_new(BIO_s_mem());
+
+ if ((int)size != BIO_write(b, buffer, size)) {
+ LogError("Error in BIO_write");
+ BIO_free_all(b);
+ certsvc_pkcs12_private_key_free(buffer);
+ return CERTSVC_FAIL;
+ }
+
+ certsvc_pkcs12_private_key_free(buffer);
+
+ *pkey = PEM_read_bio_PrivateKey(b, NULL, NULL, NULL);
+
+ BIO_free_all(b);
+
+ if (*pkey) {
+ return CERTSVC_SUCCESS;
+ }
+
+ LogError("Result is null. Openssl REASON code is: "
+ << ERR_GET_REASON(ERR_peek_last_error()));
+
+ return CERTSVC_FAIL;
+}
+
+void certsvc_pkcs12_free_evp_pkey(EVP_PKEY* pkey)
+{
+ EVP_PKEY_free(pkey);
+}
+
+int certsvc_ocsp_check(
+ CertSvcCertificate *chain,
+ int chain_size,
+ CertSvcCertificate *trusted,
+ int trusted_size,
+ const char *url,
+ int *status)
+{
+ try {
+ if (!chain || !trusted) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ return impl(chain[0].privateInstance)->
+ ocspCheck(chain,
+ chain_size,
+ trusted,
+ trusted_size,
+ url,
+ status);
+ } catch (std::bad_alloc &) {
+ return CERTSVC_BAD_ALLOC;
+ } catch (...) {}
+ return CERTSVC_FAIL;
+}
+
+int certsvc_message_verify(
+ CertSvcCertificate certificate,
+ CertSvcString message,
+ CertSvcString signature,
+ const char *algorithm,
+ int *status)
+{
+ try {
+ return impl(certificate.privateInstance)->verify(
+ certificate,
+ message,
+ signature,
+ algorithm,
+ status);
+ } catch(...) {}
+ return CERTSVC_FAIL;
+}
+
+int certsvc_base64_encode(CertSvcString message, CertSvcString *base64)
+{
+ try {
+ return impl(message.privateInstance)->base64Encode(message, base64);
+ } catch(...) {}
+ return CERTSVC_FAIL;
+}
+
+int certsvc_base64_decode(CertSvcString base64, CertSvcString *message)
+{
+ try {
+ return impl(base64.privateInstance)->base64Decode(base64, message);
+ } catch(...) {}
+ return CERTSVC_FAIL;
+}
+
+int certsvc_string_new(
+ CertSvcInstance instance,
+ const char *url,
+ int size,
+ CertSvcString *output)
+{
+ try {
+ return impl(instance)->stringNew(instance, url, size, output);
+ } catch (...) {}
+ return CERTSVC_FAIL;
+}
+
+int certsvc_string_not_managed(
+ CertSvcInstance instance,
+ const char *url,
+ int size,
+ CertSvcString *output)
+{
+ if (!output) {
+ return CERTSVC_WRONG_ARGUMENT;
+ }
+ output->privateHandler = const_cast<char*>(url);
+ output->privateLength = size;
+ output->privateInstance = instance;
+ return CERTSVC_SUCCESS;
+}
+
+void certsvc_crl_cache_functions(
+ CertSvcInstance instance,
+ CertSvcCrlCacheWrite writePtr,
+ CertSvcCrlCacheRead readPtr,
+ CertSvcCrlFree freePtr)
+{
+ impl(instance)->setCRLFunction(writePtr, readPtr, freePtr);
+}
+
+int certsvc_crl_check(
+ CertSvcCertificate certificate,
+ CertSvcCertificate *trustedStore,
+ int storeSize,
+ int force,
+ int *status,
+ void *userParam)
+{
+ try {
+ return impl(certificate.privateInstance)->crlCheck(
+ certificate,
+ trustedStore,
+ storeSize,
+ force,
+ status,
+ userParam);
+ } catch (...) {}
+ return CERTSVC_FAIL;
+}
+
+int certsvc_certificate_verify(
+ CertSvcCertificate certificate,
+ CertSvcCertificate *trusted,
+ int trustedSize,
+ CertSvcCertificate *untrusted,
+ int untrustedSize,
+ int *status)
+{
+ try {
+ return impl(certificate.privateInstance)->certificateVerify(
+ certificate,
+ trusted,
+ trustedSize,
+ untrusted,
+ untrustedSize,
+ status);
+ } catch (...) {}
+ return CERTSVC_FAIL;
+}
+
+int certsvc_pkcs12_alias_exists(CertSvcInstance instance,
+ CertSvcString pfxIdString,
+ int *is_unique)
+{
+ try {
+ return impl(instance)->pkcsNameIsUnique(pfxIdString, is_unique);
+ } catch (...) {}
+ return CERTSVC_FAIL;
+}
+
+int certsvc_pkcs12_import_from_file(CertSvcInstance instance,
+ CertSvcString path,
+ CertSvcString password,
+ CertSvcString pfxIdString)
+{
+ try {
+ return impl(instance)->pkcsImport(path, password, pfxIdString);
+ } catch (...) {}
+ return CERTSVC_FAIL;
+}
+
+int certsvc_pkcs12_get_id_list(
+ CertSvcInstance instance,
+ CertSvcStringList *pfxIdStringList)
+{
+ try {
+ return impl(instance)->getPkcsIdList(
+ instance,
+ pfxIdStringList);
+ } catch (...) {}
+ return CERTSVC_FAIL;
+}
+
+int certsvc_pkcs12_has_password(
+ CertSvcInstance instance,
+ CertSvcString filepath,
+ int *has_password)
+{
+ try {
+ return impl(instance)->pkcsHasPassword(
+ filepath,
+ has_password);
+ } catch (...) {}
+ return CERTSVC_FAIL;
+}
+
+int certsvc_pkcs12_load_certificate_list(
+ CertSvcInstance instance,
+ CertSvcString pfxIdString,
+ CertSvcCertificateList *certificateList)
+{
+ try {
+ return impl(instance)->getPkcsCertificateList(
+ instance,
+ pfxIdString,
+ certificateList);
+ } catch (...) {}
+ return CERTSVC_FAIL;
+}
+
+int certsvc_pkcs12_private_key_dup(
+ CertSvcInstance instance,
+ CertSvcString pfxIdString,
+ char **buffer,
+ size_t *size)
+{
+ try {
+ return impl(instance)->getPkcsPrivateKey(pfxIdString, buffer, size);
+ } catch (...) {}
+ return CERTSVC_FAIL;
+}
+
+void certsvc_pkcs12_private_key_free(
+ char *buffer)
+{
+ delete[] buffer;
+}
+
+int certsvc_pkcs12_delete(
+ CertSvcInstance instance,
+ CertSvcString pfxIdString)
+{
+ try {
+ return impl(instance)->pkcsDelete(pfxIdString);
+ } catch (...) {}
+ return CERTSVC_FAIL;
+}
--- /dev/null
+/**
+ * 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 pkcs12.h
+ * @author Jacek Migacz (j.migacz@samsung.com)
+ * @version 1.0
+ * @brief PKCS#12 container manipulation routines.
+ */
+#define _GNU_SOURCE
+
+#include "pkcs12.h"
+#include <cert-svc/cerror.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <openssl/err.h>
+#include <openssl/pkcs12.h>
+#include <openssl/sha.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <ss_manager.h>
+
+#define SYSCALL(call) while(((call) == -1) && (errno == EINTR))
+
+#define CERTSVC_PKCS12_STORAGE_DIR "/opt/share/cert-svc/pkcs12"
+#define CERTSVC_PKCS12_STORAGE_FILE "storage"
+#define CERTSVC_PKCS12_STORAGE_PATH CERTSVC_PKCS12_STORAGE_DIR "/" CERTSVC_PKCS12_STORAGE_FILE
+
+static const char CERTSVC_PKCS12_STORAGE_KEY_PKEY[] = "pkey";
+static const char CERTSVC_PKCS12_STORAGE_KEY_CERTS[] = "certs";
+static const gchar CERTSVC_PKCS12_STORAGE_SEPARATOR = ';';
+static const char CERTSVC_PKCS12_UNIX_GROUP[] = "ss_privatekey";
+
+static gboolean keyfile_check(const char *pathname) {
+ int result;
+ if(access(pathname, F_OK | R_OK | W_OK) == 0)
+ return TRUE;
+ SYSCALL(result = creat(pathname, S_IRUSR | S_IWUSR));
+ if (result != -1) {
+ close(result);
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+static GKeyFile *keyfile_load(const char *pathname) {
+ GKeyFile *keyfile;
+ GError *error;
+
+ if(!keyfile_check(pathname))
+ return NULL;
+ keyfile = g_key_file_new();
+ error = NULL;
+ if(!g_key_file_load_from_file(keyfile, pathname, G_KEY_FILE_KEEP_COMMENTS, &error)) {
+ g_key_file_free(keyfile);
+ return NULL;
+ }
+ return keyfile;
+}
+
+static int generate_random_filepath(char **filepath) {
+ int generator;
+ int64_t random;
+ SHA_CTX ctx;
+ unsigned char d[SHA_DIGEST_LENGTH];
+ int result;
+
+ if(!filepath)
+ return CERTSVC_WRONG_ARGUMENT;
+
+ SYSCALL(generator = open("/dev/urandom", O_RDONLY));
+ if(generator == -1)
+ return CERTSVC_FAIL;
+ SYSCALL(result = read(generator, &random, sizeof(random)));
+ if(result == -1) {
+ SYSCALL(close(generator));
+ return CERTSVC_FAIL;
+ }
+ SYSCALL(result = close(generator));
+ if(result == -1)
+ return CERTSVC_FAIL;
+
+ SHA1_Init(&ctx);
+ SHA1_Update(&ctx, &random, sizeof(random));
+ SHA1_Final(d, &ctx);
+
+ result = asprintf(filepath, "%s/" \
+ "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" \
+ "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ CERTSVC_PKCS12_STORAGE_DIR,
+ d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9],
+ d[10], d[11], d[12], d[13], d[14], d[15], d[16], d[17], d[18], d[19]);
+ return (result != -1) ? CERTSVC_SUCCESS : CERTSVC_BAD_ALLOC;
+}
+
+static int unique_filename(char **filepath, gboolean with_secure_storage) {
+ const unsigned attempts = 0xFFU;
+ unsigned trial;
+ int result;
+ ssm_file_info_t sfi;
+ gboolean exists;
+
+ trial = 0U;
+ try_again:
+ ++trial;
+ result = generate_random_filepath(filepath);
+ if(result != CERTSVC_SUCCESS)
+ return result;
+ if(with_secure_storage)
+ exists = (access(*filepath, F_OK) == 0 || ssm_getinfo(*filepath, &sfi, SSM_FLAG_DATA, CERTSVC_PKCS12_UNIX_GROUP) == 0);
+ else
+ exists = (access(*filepath, F_OK) == 0);
+ if(exists) {
+ free(*filepath);
+ if(trial + 1 > attempts)
+ return CERTSVC_FAIL;
+ else
+ goto try_again;
+ }
+ return CERTSVC_SUCCESS;
+}
+
+static char *bare_filename(char *filepath) {
+ char *needle;
+ if(!filepath)
+ return NULL;
+ needle = strrchr(filepath, '/');
+ if(!needle)
+ return NULL;
+ return *(++needle) ? needle : NULL;
+}
+
+int c_certsvc_pkcs12_alias_exists(const gchar *alias, gboolean *exists) {
+ GKeyFile *keyfile;
+
+ if(exists == NULL)
+ return CERTSVC_WRONG_ARGUMENT;
+ keyfile = keyfile_load(CERTSVC_PKCS12_STORAGE_PATH);
+ if(!keyfile)
+ return CERTSVC_IO_ERROR;
+ *exists = g_key_file_has_group(keyfile, alias);
+ g_key_file_free(keyfile);
+ return CERTSVC_SUCCESS;
+}
+
+int c_certsvc_pkcs12_import(const char *path, const char *password, const gchar *alias) {
+ int exists;
+ FILE *stream;
+ PKCS12 *container;
+ EVP_PKEY *key;
+ X509 *cert;
+ STACK_OF(X509) *certv;
+ int nicerts;
+ char *unique;
+ int result;
+ struct stat st;
+ int wr_res;
+ GKeyFile *keyfile;
+ gchar *bare;
+ gchar *pkvalue;
+ gchar **cvaluev;
+ gsize i, n;
+ gchar *data;
+ gsize length;
+
+ certv = NULL;
+ pkvalue = NULL;
+ if(!alias || strlen(alias) < 1)
+ return CERTSVC_WRONG_ARGUMENT;
+ result = c_certsvc_pkcs12_alias_exists(alias, &exists);
+ if(result != CERTSVC_SUCCESS)
+ return result;
+ if(exists == TRUE)
+ return CERTSVC_DUPLICATED_ALIAS;
+
+ keyfile = keyfile_load(CERTSVC_PKCS12_STORAGE_PATH);
+ if(!keyfile)
+ return CERTSVC_IO_ERROR;
+ if(stat(CERTSVC_PKCS12_STORAGE_PATH, &st) == -1) {
+ if(mkdir(CERTSVC_PKCS12_STORAGE_PATH, S_IRWXU | S_IRWXG | S_IRWXO) == -1) {
+ result = CERTSVC_FAIL;
+ goto free_keyfile;
+ }
+ }
+
+ if((stream = fopen(path, "rb")) == NULL) {
+ result = CERTSVC_IO_ERROR;
+ goto free_keyfile;
+ }
+ container = d2i_PKCS12_fp(stream, NULL);
+ fclose(stream);
+ if(container == NULL) {
+ result = CERTSVC_FAIL;
+ goto free_keyfile;
+ }
+ result = PKCS12_parse(container, password, &key, &cert, &certv);
+ PKCS12_free(container);
+ if(result == 0) {
+ result = CERTSVC_FAIL;
+ goto free_keyfile;
+ }
+ nicerts = certv ? sk_X509_num(certv) : 0;
+ cvaluev = (gchar **)calloc(1 + nicerts, sizeof(gchar *));
+ n = 0;
+
+ result = unique_filename(&unique, TRUE);
+ if(result != CERTSVC_SUCCESS)
+ goto clean_cert_chain_and_pkey;
+ if((stream = fopen(unique, "w")) == NULL) {
+ free(unique);
+ result = CERTSVC_IO_ERROR;
+ goto clean_cert_chain_and_pkey;
+ }
+ result = PEM_write_PrivateKey(stream, key, NULL, NULL, 0, NULL, NULL);
+ fclose(stream);
+ if(result == 0) {
+ result = CERTSVC_FAIL;
+ goto clean_cert_chain_and_pkey;
+ }
+ wr_res = ssm_write_file(unique, SSM_FLAG_DATA, CERTSVC_PKCS12_UNIX_GROUP);
+ if(wr_res != 0) {
+ free(unique);
+ result = CERTSVC_FAIL;
+ goto clean_cert_chain_and_pkey;
+ }
+ bare = bare_filename(unique);
+ if(bare) {
+ pkvalue = g_strdup(bare);
+ g_key_file_set_string(keyfile, alias, CERTSVC_PKCS12_STORAGE_KEY_PKEY, pkvalue);
+ }
+ free(unique);
+ result = unique_filename(&unique, FALSE);
+ if(result != CERTSVC_SUCCESS)
+ goto clean_cert_chain_and_pkey;
+ if((stream = fopen(unique, "w")) == NULL) {
+ free(unique);
+ result = CERTSVC_IO_ERROR;
+ goto clean_cert_chain_and_pkey;
+ }
+ result = PEM_write_X509(stream, cert);
+ fclose(stream);
+ if(result == 0) {
+ result = CERTSVC_FAIL;
+ goto clean_cert_chain_and_pkey;
+ }
+ bare = bare_filename(unique);
+ if(bare)
+ cvaluev[n++] = g_strdup(bare);
+ free(unique);
+ for(i = 0; i < nicerts; i++) {
+ result = unique_filename(&unique, FALSE);
+ if(result != CERTSVC_SUCCESS)
+ goto clean_cert_chain_and_pkey;
+ if((stream = fopen(unique, "w")) == NULL) {
+ free(unique);
+ result = CERTSVC_IO_ERROR;
+ goto clean_cert_chain_and_pkey;
+ }
+ result = PEM_write_X509_AUX(stream, sk_X509_value(certv, i));
+ fclose(stream);
+ if(result == 0) {
+ result = CERTSVC_FAIL;
+ goto clean_cert_chain_and_pkey;
+ }
+ bare = bare_filename(unique);
+ if(bare)
+ cvaluev[n++] = g_strdup(bare);
+ free(unique);
+ }
+ g_key_file_set_list_separator(keyfile, CERTSVC_PKCS12_STORAGE_SEPARATOR);
+ g_key_file_set_string_list(keyfile, alias, CERTSVC_PKCS12_STORAGE_KEY_CERTS, (const gchar * const *)cvaluev, n);
+ data = g_key_file_to_data(keyfile, &length, NULL);
+ if(data == NULL) {
+ result = CERTSVC_BAD_ALLOC;
+ goto clean_cert_chain_and_pkey;
+ }
+ if(!g_file_set_contents(CERTSVC_PKCS12_STORAGE_PATH, data, length, NULL)) {
+ result = CERTSVC_IO_ERROR;
+ goto free_data;
+ }
+ result = CERTSVC_SUCCESS;
+ free_data:
+ g_free(data);
+ clean_cert_chain_and_pkey:
+ EVP_PKEY_free(key);
+ X509_free(cert);
+ sk_X509_free(certv);
+ free(pkvalue);
+ for(i = 0; i < n; i++) {
+ g_free(cvaluev[i]);
+ }
+ free(cvaluev);
+ free_keyfile:
+ g_key_file_free(keyfile);
+ return result;
+}
+
+int c_certsvc_pkcs12_aliases_load(gchar ***aliases, gsize *naliases) {
+ GKeyFile *keyfile;
+
+ keyfile = keyfile_load(CERTSVC_PKCS12_STORAGE_PATH);
+ if(!keyfile)
+ return CERTSVC_IO_ERROR;
+ *aliases = g_key_file_get_groups(keyfile, naliases);
+ g_key_file_free(keyfile);
+ return CERTSVC_SUCCESS;
+}
+
+void c_certsvc_pkcs12_aliases_free(gchar **aliases) {
+ g_strfreev(aliases);
+}
+
+int c_certsvc_pkcs12_has_password(const char *filepath, gboolean *passworded) {
+ FILE *stream;
+ EVP_PKEY *pkey;
+ X509 *cert;
+ PKCS12 *container;
+ int result;
+
+ if(passworded == NULL)
+ return CERTSVC_WRONG_ARGUMENT;
+ if((stream = fopen(filepath, "rb")) == NULL)
+ return CERTSVC_IO_ERROR;
+ container = d2i_PKCS12_fp(stream, NULL);
+ fclose(stream);
+ if(container == NULL)
+ return CERTSVC_FAIL;
+ result = PKCS12_parse(container, NULL, &pkey, &cert, NULL);
+ PKCS12_free(container);
+ if(result == 1) {
+ EVP_PKEY_free(pkey);
+ X509_free(cert);
+ *passworded = FALSE;
+ return CERTSVC_SUCCESS;
+ }
+ else {
+ if(ERR_GET_REASON(ERR_peek_last_error()) == PKCS12_R_MAC_VERIFY_FAILURE) {
+ *passworded = TRUE;
+ return CERTSVC_SUCCESS;
+ }
+ else
+ return CERTSVC_FAIL;
+ }
+}
+
+int c_certsvc_pkcs12_load_certificates(const gchar *alias, gchar ***certs, gsize *ncerts) {
+ GKeyFile *keyfile;
+ gchar **barev;
+ gsize i;
+ keyfile = keyfile_load(CERTSVC_PKCS12_STORAGE_PATH);
+ if(!keyfile)
+ return CERTSVC_IO_ERROR;
+ g_key_file_set_list_separator(keyfile, CERTSVC_PKCS12_STORAGE_SEPARATOR);
+ barev = g_key_file_get_string_list(keyfile, alias, CERTSVC_PKCS12_STORAGE_KEY_CERTS, ncerts, NULL);
+ if(barev == NULL) {
+ *ncerts = 0;
+ goto free_keyfile;
+ }
+ *certs = g_malloc((*ncerts + 1) * sizeof(gchar *));
+ for(i = 0; i < *ncerts; i++)
+ (*certs)[i] = g_strdup_printf("%s/%s", CERTSVC_PKCS12_STORAGE_DIR, barev[i]);
+ (*certs)[*ncerts] = NULL;
+ g_strfreev(barev);
+free_keyfile:
+ g_key_file_free(keyfile);
+ return CERTSVC_SUCCESS;
+}
+
+void c_certsvc_pkcs12_free_certificates(gchar **certs) {
+ gsize i = 0;
+ if(certs == NULL)
+ return;
+ while(certs[i])
+ g_free(certs[i++]);
+ g_free(certs);
+}
+
+int c_certsvc_pkcs12_private_key_load(const gchar *alias, char **buffer, gsize *count) {
+ GKeyFile *keyfile;
+ gchar *pkey;
+ GError *error;
+ ssm_file_info_t sfi;
+ char *spkp;
+ int result;
+
+ if(!buffer)
+ return CERTSVC_WRONG_ARGUMENT;
+ keyfile = keyfile_load(CERTSVC_PKCS12_STORAGE_PATH);
+ if(!keyfile)
+ return CERTSVC_IO_ERROR;
+ error = NULL;
+ result = CERTSVC_SUCCESS;
+ pkey = g_key_file_get_string(keyfile, alias, CERTSVC_PKCS12_STORAGE_KEY_PKEY, &error);
+ if(error && error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND) {
+ *count = 0;
+ result = CERTSVC_SUCCESS;
+ }
+ else if(error)
+ result = CERTSVC_FAIL;
+ else {
+ if(asprintf(&spkp, "%s/%s", CERTSVC_PKCS12_STORAGE_DIR, pkey) == -1) {
+ spkp = NULL;
+ result = CERTSVC_BAD_ALLOC;
+ }
+ else if(ssm_getinfo(spkp, &sfi, SSM_FLAG_DATA, CERTSVC_PKCS12_UNIX_GROUP) == 0) {
+ if((*buffer = malloc(sfi.originSize))) {
+ if(ssm_read(spkp, *buffer, sfi.originSize, count, SSM_FLAG_DATA, CERTSVC_PKCS12_UNIX_GROUP) != 0) {
+ c_certsvc_pkcs12_private_key_free(*buffer);
+ result = CERTSVC_FAIL;
+ }
+ }
+ else
+ result = CERTSVC_BAD_ALLOC;
+ }
+ free(spkp);
+ g_free(pkey);
+ }
+ g_key_file_free(keyfile);
+ return result;
+}
+
+void c_certsvc_pkcs12_private_key_free(char *buffer) {
+ free(buffer);
+}
+
+int c_certsvc_pkcs12_delete(const gchar *alias) {
+ gchar **certs;
+ gsize ncerts;
+ char *pkey;
+ char *spkp;
+ int result;
+ GKeyFile *keyfile;
+ gchar *data;
+ gsize i, length;
+
+ data = NULL;
+ result = c_certsvc_pkcs12_load_certificates(alias, &certs, &ncerts);
+ if(result != CERTSVC_SUCCESS)
+ goto load_certificates_failed;
+ keyfile = keyfile_load(CERTSVC_PKCS12_STORAGE_PATH);
+ if(!keyfile) {
+ result = CERTSVC_IO_ERROR;
+ goto keyfile_load_failed;
+ }
+ pkey = g_key_file_get_string(keyfile, alias, CERTSVC_PKCS12_STORAGE_KEY_PKEY, NULL);
+ if(g_key_file_remove_group(keyfile, alias, NULL)) {
+ data = g_key_file_to_data(keyfile, &length, NULL);
+ if(data == NULL) {
+ result = CERTSVC_BAD_ALLOC;
+ goto keyfile_free;
+ }
+ if(!g_file_set_contents(CERTSVC_PKCS12_STORAGE_PATH, data, length, NULL)) {
+ result = CERTSVC_IO_ERROR;
+ goto data_free;
+ }
+ }
+ for(i = 0; i < ncerts; i++)
+ unlink(certs[i]);
+ if(pkey != NULL) {
+ if(asprintf(&spkp, "%s/%s", CERTSVC_PKCS12_STORAGE_DIR, pkey) == -1) {
+ result = CERTSVC_BAD_ALLOC;
+ goto data_free;
+ }
+ ssm_delete_file(spkp, SSM_FLAG_DATA, CERTSVC_PKCS12_UNIX_GROUP);
+ free(spkp);
+ }
+ data_free:
+ g_free(data);
+ keyfile_free:
+ g_key_file_free(keyfile);
+ keyfile_load_failed:
+ if(ncerts != 0)
+ c_certsvc_pkcs12_free_certificates(certs);
+ load_certificates_failed:
+ return result;
+}
--- /dev/null
+/**
+ * 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 pkcs12.c
+ * @author Jacek Migacz (j.migacz@samsung.com)
+ * @version 1.0
+ * @brief PKCS#12 container manipulation routines.
+ */
+#ifndef _PKCS12_H_
+#define _PKCS12_H_
+
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int c_certsvc_pkcs12_alias_exists(const gchar *alias, gboolean *exists);
+int c_certsvc_pkcs12_import(const char *path, const char *password, const gchar *alias);
+int c_certsvc_pkcs12_aliases_load(gchar ***aliases, gsize *naliases);
+void c_certsvc_pkcs12_aliases_free(gchar **aliases);
+int c_certsvc_pkcs12_has_password(const char *filepath, gboolean *passworded);
+int c_certsvc_pkcs12_load_certificates(const gchar *alias, gchar ***certificates, gsize *ncertificates);
+void c_certsvc_pkcs12_free_certificates(gchar **certs);
+int c_certsvc_pkcs12_private_key_load(const gchar *alias, char **pkey, gsize *count);
+void c_certsvc_pkcs12_private_key_free(char *buffer);
+int c_certsvc_pkcs12_delete(const gchar *alias);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/*
+ * 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 scoped_fclose.h
+ * @author Piotr Marcinkiewicz (p.marcinkiew@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of scoped fclose RAII
+ */
+#ifndef WRT_ENGINE_SRC_COMMON_SCOPED_GPOINTER_H
+#define WRT_ENGINE_SRC_COMMON_SCOPED_GPOINTER_H
+
+#include <cstddef>
+#include <glib-object.h>
+
+#include <dpl/scoped_resource.h>
+#include <dpl/assert.h>
+
+namespace WRT {
+struct ScopedGPointerPolicy
+{
+ typedef gpointer Type;
+ static Type NullValue()
+ {
+ return NULL;
+ }
+ static void Destroy(Type pointer)
+ {
+ if (pointer != NULL) {
+ g_object_unref(pointer);
+ }
+ }
+};
+
+template <typename Class>
+class ScopedGPointer : public DPL::ScopedResource<ScopedGPointerPolicy>
+{
+ typedef ScopedGPointerPolicy Policy;
+ typedef DPL::ScopedResource<Policy> BaseType;
+
+ public:
+ explicit ScopedGPointer(typename Policy::Type pointer =
+ Policy::NullValue()) :
+ BaseType(pointer)
+ {
+ }
+
+ Class *operator->() const throw()
+ {
+ Assert(this->m_value != Policy::NullValue() &&
+ "Dereference of scoped NULL pointer!");
+ return static_cast<Class *>(this->m_value);
+ }
+
+ Class & operator *() const throw()
+ {
+ Assert(this->m_value != Policy::NullValue() &&
+ "Dereference of scoped NULL pointer!");
+ return *static_cast<Class *>(this->m_value);
+ }
+};
+} // namespace WRT
+
+#endif // WRT_ENGINE_SRC_COMMON_SCOPED_GPOINTER_H