summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt178
-rw-r--r--LICENSE.Apache-2.0203
-rw-r--r--[-rwxr-xr-x]LICENSE.Flora0
-rw-r--r--[-rwxr-xr-x]NOTICE0
-rwxr-xr-xbin/arm/drm_tizen_initializebin41932 -> 0 bytes
-rwxr-xr-xbin/ix86/drm_tizen_initializebin55604 -> 0 bytes
-rw-r--r--drm-service-core-tizen.manifest9
-rw-r--r--[-rwxr-xr-x]drm-service-core-tizen.pc.in2
-rw-r--r--include/drm-oem-sapps.h274
-rw-r--r--include/drm-tizen-apps.h116
-rw-r--r--include/drm-tizen-error.h95
-rw-r--r--include/drm-tizen-mid.h59
-rwxr-xr-xlib/arm/libdrm-service-core-tizen.so.0.2.9bin182748 -> 0 bytes
-rwxr-xr-xlib/ix86/libdrm-service-core-tizen.so.0.2.9bin233344 -> 0 bytes
-rwxr-xr-x[-rw-r--r--]packaging/drm-service-core-tizen.spec98
-rw-r--r--resource/ro_root_cert.pem27
-rw-r--r--service/drm-tapps-initialize.cpp124
-rw-r--r--service/drm-tapps.cpp428
-rw-r--r--tadcore/DrmFileHandleMgr/DrmFileApi.cpp171
-rw-r--r--tadcore/DrmFileHandleMgr/DrmFileHandler.cpp503
-rw-r--r--tadcore/DrmFileHandleMgr/DrmFileMgr.cpp137
-rw-r--r--tadcore/Svc/DrmTdcSvc.cpp636
-rw-r--r--tadcore/TADCCore/TADC_Core.cpp1741
-rw-r--r--tadcore/TADCCore/TADC_Sub.cpp83
-rw-r--r--tadcore/TADCCore/TADC_Util.cpp218
-rw-r--r--tadcore/TADCInterface/DUIDGenerator.cpp48
-rw-r--r--tadcore/TADCInterface/TADC_IF.cpp551
-rw-r--r--tadcore/XMLParser/CPointerArray.cpp128
-rw-r--r--tadcore/XMLParser/CXMLAttribute.cpp87
-rw-r--r--tadcore/XMLParser/CXMLElement.cpp185
-rw-r--r--tadcore/XMLParser/CXMLFile.cpp424
-rw-r--r--tadcore/include/CPointerArray.h57
-rw-r--r--tadcore/include/CXMLAttribute.h43
-rw-r--r--tadcore/include/CXMLElement.h61
-rw-r--r--tadcore/include/CXMLFile.h60
-rw-r--r--tadcore/include/DUIDGenerator.h29
-rw-r--r--tadcore/include/DrmFileApi.h47
-rw-r--r--tadcore/include/DrmFileHandler.h58
-rw-r--r--tadcore/include/DrmFileMgr.h39
-rw-r--r--tadcore/include/DrmTdcSvc.h194
-rw-r--r--tadcore/include/TADC_Core.h186
-rw-r--r--tadcore/include/TADC_ErrorCode.h23
-rw-r--r--tadcore/include/TADC_IF.h59
-rw-r--r--tadcore/include/TADC_Sub.h25
-rw-r--r--tadcore/include/TADC_Util.h24
-rw-r--r--tadcore/include/TadcTypes.h51
-rw-r--r--tappsd/inc/DTapps2Base64.h39
-rw-r--r--tappsd/inc/DTapps2HMAC.h39
-rw-r--r--tappsd/inc/DTapps2Rights.h96
-rw-r--r--tappsd/inc/DTapps2SqliteDB.h67
-rw-r--r--tappsd/inc/DTapps2Time.h39
-rw-r--r--tappsd/inc/drm_intf_tapps.h244
-rw-r--r--tappsd/src/db/DTapps2SqlData.cpp46
-rw-r--r--tappsd/src/db/DTapps2SqliteDB.cpp958
-rw-r--r--tappsd/src/intf/drm_intf_tapps.cpp156
-rw-r--r--tappsd/src/rights/DTapps2Rights.cpp1288
-rw-r--r--tappsd/src/util/DTapps2Base64.cpp125
-rw-r--r--tappsd/src/util/DTapps2HMAC.cpp88
-rw-r--r--tappsd/src/util/DTapps2Time.cpp136
-rw-r--r--test/CMakeLists.txt118
-rw-r--r--test/drm_testapps.cpp2987
-rw-r--r--test/drm_testutil.cpp813
-rw-r--r--test/drm_testutil.h86
-rw-r--r--test/sample_contents/DB/.dtapps.dbbin0 -> 16384 bytes
-rw-r--r--test/sample_contents/DB/.dtapps.db-journalbin0 -> 12824 bytes
-rw-r--r--test/sample_contents/DCF/38EIfBurLJ.tpkbin0 -> 1631570 bytes
-rw-r--r--test/sample_contents/DCF/8SPXfqc6iL.tpkbin0 -> 705914 bytes
-rw-r--r--test/sample_contents/DCF/FightGuiIF.tpkbin0 -> 45194636 bytes
-rw-r--r--test/sample_contents/DCF/X5YVR2zmQZ.tpkbin0 -> 31947 bytes
-rw-r--r--test/sample_contents/DCF/ZdAXXZx2HZ.tpkbin0 -> 146995 bytes
-rw-r--r--test/sample_contents/DCF/basiccoreuiapp_drm.tpkbin0 -> 51925 bytes
-rw-r--r--test/sample_contents/DCF/lXs4HhBlYZ.tpkbin0 -> 75393 bytes
-rw-r--r--test/sample_contents/DecryptedApp/38EIfBurLJ_dec.tpkbin0 -> 1630724 bytes
-rw-r--r--test/sample_contents/DecryptedApp/8SPXfqc6iL_dec.tpkbin0 -> 705072 bytes
-rw-r--r--test/sample_contents/DecryptedApp/FightGuiIF_dec.tpkbin0 -> 45193789 bytes
-rw-r--r--test/sample_contents/DecryptedApp/basiccoreuiapp_signed.tpkbin0 -> 51922 bytes
-rw-r--r--test/sample_contents/DecryptedTPK/X5YVR2zmQZ.tpk.decbin0 -> 31105 bytes
-rw-r--r--test/sample_contents/DecryptedTPK/ZdAXXZx2HZ.tpk.decbin0 -> 146152 bytes
-rw-r--r--test/sample_contents/DecryptedTPK/lXs4HhBlYZ.tpk.decbin0 -> 74551 bytes
-rw-r--r--test/sample_contents/KEYS/ro_test_root_ca.key27
-rw-r--r--test/sample_contents/KEYS/ro_test_root_ca.pem80
-rw-r--r--test/sample_contents/KEYS/ro_test_second_ca.key27
-rw-r--r--test/sample_contents/KEYS/ro_test_second_ca.pem80
-rw-r--r--test/sample_contents/KEYS/ro_test_signer.key27
-rw-r--r--test/sample_contents/KEYS/ro_test_signer.pem83
-rw-r--r--test/sample_contents/RO/38EIfBurLJ-1.0.2.cert_chain_invalid.ro21
-rw-r--r--test/sample_contents/RO/38EIfBurLJ-1.0.2.cert_invalid.ro21
-rw-r--r--test/sample_contents/RO/38EIfBurLJ-1.0.2.cert_only_selfsigned.ro20
-rw-r--r--test/sample_contents/RO/38EIfBurLJ-1.0.2.ro21
-rw-r--r--test/sample_contents/RO/38EIfBurLJ-1.0.2.ro_template21
-rw-r--r--test/sample_contents/RO/38EIfBurLJ-1.0.2.signature_invalid.ro21
-rw-r--r--test/sample_contents/RO/8SPXfqc6iL-1.0.0.ro21
-rw-r--r--test/sample_contents/RO/8SPXfqc6iL-1.0.0.signature_invalid.ro21
-rw-r--r--test/sample_contents/RO/FightGuiIF-1.0.0.ro21
-rw-r--r--test/sample_contents/RO/FightGuiIF-1.0.0.signature_invalid.ro21
-rw-r--r--test/sample_contents/RO/X5YVR2zmQZ.cert_chain_invalid.ro37
-rw-r--r--test/sample_contents/RO/X5YVR2zmQZ.ro37
-rw-r--r--test/sample_contents/RO/X5YVR2zmQZ.signature_invalid.ro37
-rw-r--r--test/sample_contents/RO/ZdAXXZx2HZ.cert_invalid.ro37
-rw-r--r--test/sample_contents/RO/ZdAXXZx2HZ.ro37
-rw-r--r--test/sample_contents/RO/ZdAXXZx2HZ.signature_invalid.ro37
-rw-r--r--test/sample_contents/RO/dtapps.dbbin0 -> 16384 bytes
-rw-r--r--test/sample_contents/RO/lXs4HhBlYZ.cert_only_selfsigned.ro36
-rw-r--r--test/sample_contents/RO/lXs4HhBlYZ.ro37
-rw-r--r--test/sample_contents/RO/lXs4HhBlYZ.signature_invalid.ro37
-rw-r--r--test/sample_contents/ROv2/sample_1.ro21
-rw-r--r--test/sample_contents/ROv2/sample_2.ro21
107 files changed, 15375 insertions, 338 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 86eefa9..d59040b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,28 +1,152 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
-SET (this_target drm-service-core-tizen)
-
-CONFIGURE_FILE(drm-service-core-tizen.pc.in ${CMAKE_SOURCE_DIR}/drm-service-core-tizen.pc @ONLY)
-
-INSTALL(FILES ${CMAKE_SOURCE_DIR}/drm-service-core-tizen.pc DESTINATION lib/pkgconfig)
-
-INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/include/ DESTINATION /usr/include/drm-tizen/ FILES_MATCHING PATTERN "*.h")
-
-IF("${ARCH}" MATCHES "arm")
-INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/arm/ DESTINATION /usr/lib FILES_MATCHING PATTERN "*"
- PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ
- GROUP_EXECUTE GROUP_READ
- WORLD_EXECUTE WORLD_READ)
-INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/bin/arm/ DESTINATION /usr/bin FILES_MATCHING PATTERN "*"
- PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ
- GROUP_EXECUTE GROUP_READ
- WORLD_EXECUTE WORLD_READ)
-ELSE("${ARCH}" MATCHES "arm")
-INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/ix86/ DESTINATION /usr/lib FILES_MATCHING PATTERN "*"
- PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ
- GROUP_EXECUTE GROUP_READ
- WORLD_EXECUTE WORLD_READ)
-INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/bin/ix86/ DESTINATION /usr/bin FILES_MATCHING PATTERN "*"
- PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ
- GROUP_EXECUTE GROUP_READ
- WORLD_EXECUTE WORLD_READ)
-ENDIF("${ARCH}" MATCHES "arm")
+PROJECT(drm-service-core-tizen CXX)
+
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(EXEC_PREFIX "\${prefix}")
+SET(LIBDIR "\${prefix}/lib")
+SET(INCLUDEDIR "\${prefix}/include")
+
+SET(DRMTESTUTIL drm_test_tizen)
+SET(DRMTAPPSINITIALIZE drm_tizen_initialize)
+
+IF (CMAKE_BUILD_TYPE MATCHES "DEBUG")
+ ADD_DEFINITIONS("-DTIZEN_DEBUG_ENABLE")
+ ADD_DEFINITIONS("-DBUILD_TYPE_DEBUG")
+ENDIF (CMAKE_BUILD_TYPE MATCHES "DEBUG")
+
+INCLUDE(FindPkgConfig)
+
+ADD_DEFINITIONS("-DISSUER_ROOT_CERTS_DIR=\"${TZ_SYS_SHARE}/tizen_app_drm/root_certs\"")
+ADD_DEFINITIONS("-DDB_PATH=\"${TZ_SYS_DB}/.dtapps.db\"")
+
+
+############################# compiler flags ##################################
+SET(CMAKE_C_FLAGS_PROFILING "-g -O0 -pg -Wp,-U_FORTIFY_SOURCE")
+SET(CMAKE_CXX_FLAGS_PROFILING "-g -std=c++0x -O0 -pg -Wp,-U_FORTIFY_SOURCE")
+SET(CMAKE_C_FLAGS_DEBUG "-g -O0 -ggdb -Wp,-U_FORTIFY_SOURCE")
+SET(CMAKE_CXX_FLAGS_DEBUG "-g -std=c++0x -O0 -ggdb -Wp,-U_FORTIFY_SOURCE")
+SET(CMAKE_C_FLAGS_RELEASE "-g -O2")
+SET(CMAKE_CXX_FLAGS_RELEASE "-g -std=c++0x -O2")
+SET(CMAKE_C_FLAGS_CCOV "-g -O2 --coverage")
+SET(CMAKE_CXX_FLAGS_CCOV "-g -std=c++0x -O2 --coverage")
+
+ADD_DEFINITIONS("-fPIC")
+
+INCLUDE_DIRECTORIES(
+ SYSTEM
+ ${CMAKE_CURRENT_SOURCE_DIR}/tadcore/include
+ ${CMAKE_CURRENT_SOURCE_DIR}/tappsd/inc
+ ${CMAKE_CURRENT_SOURCE_DIR}/include
+)
+
+pkg_check_modules(DRM_SERVICE_CORE_DEP
+ REQUIRED
+ dlog
+ db-util
+ openssl
+ dukgenerator
+ cryptsvc
+ libtzplatform-config
+)
+
+INCLUDE_DIRECTORIES(${DRM_SERVICE_CORE_DEP_INCLUDE_DIRS})
+
+SET(SRCS
+ tadcore/TADCCore/TADC_Core.cpp
+ tadcore/TADCCore/TADC_Sub.cpp
+ tadcore/TADCCore/TADC_Util.cpp
+ tadcore/TADCInterface/TADC_IF.cpp
+ tadcore/Svc/DrmTdcSvc.cpp
+ tappsd/src/intf/drm_intf_tapps.cpp
+ tadcore/XMLParser/CPointerArray.cpp
+ tadcore/XMLParser/CXMLAttribute.cpp
+ tadcore/XMLParser/CXMLElement.cpp
+ tadcore/XMLParser/CXMLFile.cpp
+ tappsd/src/rights/DTapps2Rights.cpp
+ tappsd/src/db/DTapps2SqlData.cpp
+ tappsd/src/db/DTapps2SqliteDB.cpp
+ tappsd/src/util/DTapps2Base64.cpp
+ tappsd/src/util/DTapps2HMAC.cpp
+ tappsd/src/util/DTapps2Time.cpp
+ service/drm-tapps.cpp
+ tadcore/DrmFileHandleMgr/DrmFileHandler.cpp
+ tadcore/DrmFileHandleMgr/DrmFileMgr.cpp
+ tadcore/DrmFileHandleMgr/DrmFileApi.cpp
+
+ #for deviceId
+ tadcore/TADCInterface/DUIDGenerator.cpp
+)
+
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS})
+
+SET_TARGET_PROPERTIES(
+ ${PROJECT_NAME}
+ PROPERTIES
+ COMPILE_FLAGS " -fvisibility=hidden"
+ SOVERSION ${MAJORVER}
+ VERSION ${FULLVER}
+)
+
+TARGET_LINK_LIBRARIES(${PROJECT_NAME}
+ ${DRM_SERVICE_CORE_DEP_LIBRARIES}
+ -ldevice_info # libdevice_info.so in cryptsvc.
+)
+
+#################################################################
+pkg_check_modules(DRM_INITIALIZE_DEP
+ REQUIRED
+ dlog
+ db-util
+ openssl
+ dukgenerator
+# cryptsvc
+)
+
+INCLUDE_DIRECTORIES(${DRM_INITIALIZE_DEP_INCLUDE_DIRS})
+
+SET(DRMTAPPSINITIALIZE_SRCS
+ service/drm-tapps-initialize.cpp
+ tappsd/src/intf/drm_intf_tapps.cpp
+ tappsd/src/db/DTapps2SqliteDB.cpp
+ tappsd/src/db/DTapps2SqlData.cpp
+)
+
+FIND_PROGRAM(UNAME NAMES uname)
+EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH")
+
+IF("${ARCH}" STREQUAL "arm")
+ ADD_DEFINITIONS("-DTARGET")
+ MESSAGE("add -DTARGET")
+ENDIF("${ARCH}" STREQUAL "arm")
+
+# -fPIE and -pie flag is added for ASLR
+SET_SOURCE_FILES_PROPERTIES(
+ ${DRMTAPPSINITIALIZE_SRCS}
+ PROPERTIES
+ COMPILE_FLAGS "-fPIE")
+
+ADD_EXECUTABLE(${DRMTAPPSINITIALIZE} ${DRMTAPPSINITIALIZE_SRCS})
+
+TARGET_LINK_LIBRARIES(${DRMTAPPSINITIALIZE}
+ ${DRM_INITIALIZE_DEP_LIBRARIES}
+ -pie)
+
+#################################################################
+
+CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY)
+
+INSTALL(FILES ${PROJECT_NAME}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
+
+INSTALL(FILES resource/ro_root_cert.pem
+ DESTINATION ${TZ_SYS_SHARE}/tizen_app_drm/root_certs)
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR})
+INSTALL(TARGETS ${DRMTAPPSINITIALIZE} DESTINATION bin)
+
+INSTALL(DIRECTORY include/ DESTINATION ${INCLUDEDIR}/drm-tizen/)
+
+#################################################################
+
+IF(DEFINED BUILD_TEST_DRM_SERVICE_CORE_TIZEN)
+ADD_SUBDIRECTORY(test)
+ENDIF(DEFINED BUILD_TEST_DRM_SERVICE_CORE_TIZEN)
diff --git a/LICENSE.Apache-2.0 b/LICENSE.Apache-2.0
new file mode 100644
index 0000000..247c97d
--- /dev/null
+++ b/LICENSE.Apache-2.0
@@ -0,0 +1,203 @@
+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 [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/LICENSE.Flora b/LICENSE.Flora
index 571fe79..571fe79 100755..100644
--- a/LICENSE.Flora
+++ b/LICENSE.Flora
diff --git a/NOTICE b/NOTICE
index e8d1acb..e8d1acb 100755..100644
--- a/NOTICE
+++ b/NOTICE
diff --git a/bin/arm/drm_tizen_initialize b/bin/arm/drm_tizen_initialize
deleted file mode 100755
index 9e28cf9..0000000
--- a/bin/arm/drm_tizen_initialize
+++ /dev/null
Binary files differ
diff --git a/bin/ix86/drm_tizen_initialize b/bin/ix86/drm_tizen_initialize
deleted file mode 100755
index f93bc3c..0000000
--- a/bin/ix86/drm_tizen_initialize
+++ /dev/null
Binary files differ
diff --git a/drm-service-core-tizen.manifest b/drm-service-core-tizen.manifest
index bea6593..a76fdba 100644
--- a/drm-service-core-tizen.manifest
+++ b/drm-service-core-tizen.manifest
@@ -1,12 +1,5 @@
<manifest>
- <define>
- <domain name="drm-service-core-tizen" />
- </define>
<request>
- <domain name="drm-service-core-tizen" />
+ <domain name="_" />
</request>
- <assign>
- <filesystem path="/usr/lib/libdrm-service-core-tizen.so" label="_" />
- <filesystem path="/usr/bin/drm_tizen_initialize" label="_" />
- </assign>
</manifest>
diff --git a/drm-service-core-tizen.pc.in b/drm-service-core-tizen.pc.in
index e03267f..1c0a8af 100755..100644
--- a/drm-service-core-tizen.pc.in
+++ b/drm-service-core-tizen.pc.in
@@ -1,6 +1,6 @@
prefix=@PREFIX@
exec_prefix=@EXEC_PREFIX@
-libdir=@LIBDIR@
+libdir=@LIB_INSTALL_DIR@
includedir=@INCLUDEDIR@
Name: drm-service-core-tizen
diff --git a/include/drm-oem-sapps.h b/include/drm-oem-sapps.h
deleted file mode 100644
index b66a212..0000000
--- a/include/drm-oem-sapps.h
+++ /dev/null
@@ -1,274 +0,0 @@
-// Copyright (c) 2013 Samsung Electronics Co., Ltd.
-//
-// Licensed under the Flora License, Version 1.1 (the License);
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://floralicense.org/license/
-
-//
-// 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 __DRM_OEM_SAPPS_H__
-#define __DRM_OEM_SAPPS_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <time.h>
-
-#define DRM_SAPPS_SUCCESS 0
-#define DRM_SAPPS_LIC_VALID 1
-#define DRM_SAPPS_LIC_SUSPEND 2
-
-#define DRM_SAPPS_INVALID_ARG -1000
-#define DRM_SAPPS_PARSING_ERROR -999
-#define DRM_SAPPS_DB_ERROR -998
-#define DRM_SAPPS_INSUFFICIENT_MEMORY -997
-#define DRM_SAPPS_INTERNAL_ERROR -996
-#define DRM_SAPPS_FILE_ERROR -995
-
-#define DRM_SAPPS_LIC_EXPIRED_DATETIME -994
-#define DRM_SAPPS_LIC_EXPIRED_COUNT -993
-#define DRM_SAPPS_LIC_NO_LICENCE -992
-#define DRM_SAPPS_LIC_IMEI_MISMATCH -991
-#define DRM_SAPPS_LIC_PNUM_MISMATCH -990
-
-#define DRM_SAPPS_UNKNOWN_ERROR -1
-
-typedef struct
-{
- unsigned int IsLicenseValid; /**<whether license is valid or not */
- unsigned int OrgCount; /**<Original Count */
- unsigned int CurCount; /**<Current Count */
- struct tm starttime; /**<starttime in the format of struct tm */
- struct tm endtime; /**<endtime in the format of struct tm */
- struct tm securetime; /**<securetime in the format of struct tm */
-} drm_sapps_license_info;
-
-typedef struct _drm_sapps_license_list{
- struct _drm_sapps_license_list* pnext;
- drm_sapps_license_info LicenseInfo;
-} drm_sapps_license_list;
-
-/**
- * An application can request generate request for getting License.
- *
- * @param[in] pRespBuf Response Data String of the Purchase Request ( Null terminator string )
- * @param[in] respBufLen pResBuf Length
- * @param[in][out] pReqBuf License Request Data
- * @param[in][out] pReqBufLen IN : pReqBuf Length, OUT : Rights Request Data String Size ( including null terminator )
- * @param[in][out] pLicenseUrl License Acquisition URL Data
- * @param[in][out] pLicenseUrlLen IN : pLicenseUrl Length, OUT : Rights Issuer Server URL Data String Size ( including null terminator )
- * @return This function returns 1 on success or 0 on failure.
- * @remarks
- * @see drm_sdc_generate_purchase_request
- * @since
- */
-int drm_oem_sapps_generate_license_request(const char *pRespBuf, unsigned int respBufLen, char *pReqBuf, unsigned int *pReqBufLen, char *pLicenseUrl, unsigned int *pLicenseUrlLen);
-
-/**
- * An application can get SAD license which is encrypted.
- *
- * @param[in] pRespBuf Response Data String of the Rights Request ( Null terminator string )
- * @param[in] respBufLen pResBuf Length
- * @return This function returns 1 on success or 0 on failure.
- * @remarks
- * @see
- * @since
- */
- int drm_oem_sapps_register_license(const char *pRespBuf, unsigned int respBufLen);
-
-/**
- * API for checks whether the app drm file or not
- *
- * @param[in] pDcfPath File path that to be checked whether the app drm file or not
- * @param[in] dcfPathLen File path length that to be checked whether the app drm file or not
- * @return This function can return any of the following codes
- * SADC_NOTSADCFILE_ERROR = 0x0640
- * SADC_PARAMETER_ERROR = 0X0660
- * SADC_FILE_READ_ERROR = 0x0703
- * SADC_MEMAlOC_ERROR = 0x0662
- * @remarks
- * @remarks
- * @see
- * @since
- */
- int drm_oem_sapps_is_drm_file(const char *pDcfPath, int dcfPathLen);
-
-/**
- * An application can get decrypted contents(Apps) which is encrypted.
- *
- * @param[in] pSADCFilepath SDC DRM File Path
- * @param[in] sadcFileLen SDC DRM File length
- * @param[in] pDecryptedFile Decrypted File Path
- * @param[in] decryptedFileLen Decrypted File length
- * @return
- * SADC_SUCCESS = 0
- * SADC_PARAMETER_ERROR = 0X0660
- * SADC_GET_FILEHEADER_ERROR = 0x0703
- * SADC_GET_CEK_ERROR = 0x0704
- * SADC_DECRYPT_PACKAGE_ERROR = 0x0705
- * @remarks
- * @see
- * @since
- */
-//Decrypt DRM File
- int drm_oem_sapps_decrypt_package ( const char *pSADCFilepath, int sadcFileLen, const char *pDecryptedFile, int decryptedFileLen );
-
-/**
- * API for checks whether the app drm file or not
- *
- * @param[in] pDcfPath File path that to be checked whether the app drm file or not
- * @param[in] dcfPathLen File path length that to be checked whether the app drm file or not
- * @return This function can return any of the following codes
- * SADC_SUCCESS = 0
- * SADC_NOTSADCFILE_ERROR = 0x0640
- * SADC_PARAMETER_ERROR = 0X0660
- * SADC_FILE_READ_ERROR = 0x0703
- * SADC_MEMAlOC_ERROR = 0x0662
- * @remarks
- * @remarks
- * @see
- * @since
- */
- int drm_oem_sapps_is_drm_app(const char *pszCid, int cidLen);
-
- int drm_oem_sapps_uninstall_license(const char *szCid, int cidLen);
-
-/**
- * An application can get file Header Info ( CID, License URL )
- *
- * @param[in] pSADCFilepath file path of Samsung Apps DRM contents
- * @param[out] cid contents id of Samsung Apps DRM
- * @param[in] cidLength Length of CID.
- * @param[out] riurl Right Issuer URL
- * @param[in] riurlLength Length of Right Issuer URL
- * @return This function returns 1 on success or 0 on failure.
- * @remarks
- * @see
- * @since
- */
- int drm_oem_sapps_get_file_header( const char *pSADCFilepath, char *cid, unsigned int cidLength, char *riurl, unsigned int riurlLength );
-
-/**
- * An application can request purchase request for getting License.
- *
- * @param[in] pSADCFilepath File path of Samsung Apps DRM contents
- * @param[out] pReqBuf Purchase Request Data
- * @param[in][out] pReqBufLen IN : pReqBuf Length, OUT : Purchase Request Data String Size ( including null terminator )
- * @param[out] pLicenseUrl License Acquisition URL Data
- * @param[in][out] pLicenseUrlLen IN : pLicenseUrl Length, OUT : License Server URL Data String Size ( including null terminator )
- * @return This function returns 1 on success or 0 on failure.
- * @remarks
- * @see DrmSdcGenerateLicenseRequest
- * @since
- */
- int drm_oem_sapps_generate_purchase_request ( const char *pSADCFilepath, char *pReqBuf, unsigned int *pReqBufLen, char *pLicenseUrl, unsigned int *pLicenseUrlLen );
-
-/**
- * An application can check contents(Apps) which has a valid licence.
- *
- * @param[in] szCid Content ID(CID) of the Samsung Apps contents
- * @return This function can return any of the following codes
- * DRM_SAPPS_SUCCESS = 0 <success
- * DRM_SAPPS_LIC_VALID = 1 <License is valid
- * DRM_SAPPS_LIC_SUSPEND = 2 <License is valid but for future use
- * DRM_SAPPS_INVALID_ARG = -1000 <invalid argument
- * DRM_SAPPS_PARSING_ERROR = -999 <parsing contents or rights error
- * DRM_SAPPS_DB_ERROR = -998 <data base error
- * DRM_SAPPS_INSUFFICIENT_MEMORY = -997 <memory error
- * DRM_SAPPS_INTERNAL_ERROR = -996 <processing error
- * DRM_SAPPS_FILE_ERROR = -995 <file error
- * DRM_SAPPS_LIC_EXPIRED_DATETIME = -994 <Datetime License is expired
- * DRM_SAPPS_LIC_EXPIRED_COUNT = -993 <Count License is expired
- * DRM_SAPPS_LIC_NO_LICENCE = -992 <No License
- * DRM_SAPPS_LIC_IMEI_MISMATCH = -991 <IMEI is mismatching
- * DRM_SAPPS_LIC_PNUM_MISMATCH = -990 <PNUM is mismatching
- * DRM_SAPPS_UNKNOWN_ERROR = -1 <dummy error value
- * @remarks
- * @see drm_sdc_get_file_header
- * @since
- */
- int drm_oem_sapps_has_valid_license ( const char *szCid );
-
-/**
- * An application can update license of Samsung Apps contents.
- *
- * @param[in] szCid Content ID(CID) of the Samsung Apps contents
- * @return This function can return any of the following codes
- * DRM_SAPPS_SUCCESS = 0 <success
- * DRM_SAPPS_LIC_VALID = 1 <License is valid
- * DRM_SAPPS_LIC_SUSPEND = 2 <License is valid but for future use
- * DRM_SAPPS_INVALID_ARG = -1000 <invalid argument
- * DRM_SAPPS_PARSING_ERROR = -999 <parsing contents or rights error
- * DRM_SAPPS_DB_ERROR = -998 <data base error
- * DRM_SAPPS_INSUFFICIENT_MEMORY = -997 <memory error
- * DRM_SAPPS_INTERNAL_ERROR = -996 <processing error
- * DRM_SAPPS_FILE_ERROR = -995 <file error
- * DRM_SAPPS_LIC_EXPIRED_DATETIME = -994 <Datetime License is expired
- * DRM_SAPPS_LIC_EXPIRED_COUNT = -993 <Count License is expired
- * DRM_SAPPS_LIC_NO_LICENCE = -992 <No License
- * DRM_SAPPS_LIC_IMEI_MISMATCH = -991 <IMEI is mismatching
- * DRM_SAPPS_LIC_PNUM_MISMATCH = -990 <PNUM is mismatching
- * DRM_SAPPS_UNKNOWN_ERROR = -1 <dummy error value
- * @remarks This API must be called before rendering Samsung Apps contents
- * @see
- * @since
- */
- int drm_oem_sapps_consume_license( const char *szCid );
-
-/**
- * An application can get license information for Samsung Apps content with given CID.
- *
- * @param[in] szCid Content ID(CID) of the Samsung Apps contents
- * @param[out] LicenseInfoList License information list
- * @return This function can return any of the following codes
- * DRM_SAPPS_SUCCESS = 0 <success
- * DRM_SAPPS_LIC_VALID = 1 <License is valid
- * DRM_SAPPS_LIC_SUSPEND = 2 <License is valid but for future use
- * DRM_SAPPS_INVALID_ARG = -1000 <invalid argument
- * DRM_SAPPS_PARSING_ERROR = -999 <parsing contents or rights error
- * DRM_SAPPS_DB_ERROR = -998 <data base error
- * DRM_SAPPS_INSUFFICIENT_MEMORY = -997 <memory error
- * DRM_SAPPS_INTERNAL_ERROR = -996 <processing error
- * DRM_SAPPS_FILE_ERROR = -995 <file error
- * DRM_SAPPS_LIC_EXPIRED_DATETIME = -994 <Datetime License is expired
- * DRM_SAPPS_LIC_EXPIRED_COUNT = -993 <Count License is expired
- * DRM_SAPPS_LIC_NO_LICENCE = -992 <No License
- * DRM_SAPPS_LIC_IMEI_MISMATCH = -991 <IMEI is mismatching
- * DRM_SAPPS_LIC_PNUM_MISMATCH = -990 <PNUM is mismatching
- * DRM_SAPPS_UNKNOWN_ERROR = -1 <dummy error value
- * @remarks
- * @see
- * @since
- */
- int drm_oem_sapps_get_license_info( const char *szCid ,drm_sapps_license_list **LicenseInfoList );
-
-/**
- * An application frees license information list for Samsung Apps contents.
- *
- * @param[in] pLicenseInfoList License information list pointer
- * @return
- * @remarks This should be called after using LicenseInfoList recevied in drm_oem_sapps_get_license_info.
- * @remarks Memory is allocated for LicenseInfoList in drm_oem_sapps_get_license_info that need to be freed by calling drm_oem_sapps_free_license_info
- * @see drm_oem_sapps_get_license_info
- * @since
- */
- void drm_oem_sapps_free_license_info(drm_sapps_license_list **pLicenseInfoList);
-/**
-*@}
-*/ /* Doxygen : addtogroup*/
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/drm-tizen-apps.h b/include/drm-tizen-apps.h
new file mode 100644
index 0000000..eed6922
--- /dev/null
+++ b/include/drm-tizen-apps.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 drm-service-apps.h
+ * @author Sunggun Jung <sunggun.jung@samsung.com>
+ *
+ */
+
+#ifndef __DRM_TIZEN_APPS_H__
+#define __DRM_TIZEN_APPS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <time.h>
+#include "drm-tizen-error.h"
+
+
+/**
+* @internal
+* @defgroup DRM-TAPPS drm-tapps
+* @{
+*/
+
+/**
+ * An application can request generate request for getting License.
+ *
+ * @param[in] pRespBuf Response Data String of the Purchase Request ( Null terminator string )
+ * @param[in] respBufLen pResBuf Length
+ * @param[in][out] pReqBuf License Request Data
+ * @param[in][out] pReqBufLen IN : pReqBuf Length, OUT : Rights Request Data String Size ( including null terminator )
+ * @param[in][out] pLicenseUrl License Acquisition URL Data
+ * @param[in][out] pLicenseUrlLen IN : pLicenseUrl Length, OUT : Rights Issuer Server URL Data String Size ( including null terminator )
+ * @return This function returns TADC_SUCCESS(1) on success or an integer value other than 1 on failure.
+ * @remarks
+ * @see drm_tdc_generate_purchase_request
+ * @since
+ */
+int drm_tizen_generate_license_request(const char *pRespBuf, unsigned int respBufLen, char *pReqBuf, unsigned int *pReqBufLen, char *pLicenseUrl, unsigned int *pLicenseUrlLen);
+
+/**
+ * An application can get TAD license which is encrypted.
+ *
+ * @param[in] pRespBuf Response Data String of the Rights Request ( Null terminator string )
+ * @param[in] respBufLen pResBuf Length
+ * @return This function returns TADC_SUCCESS(1) on success or an integer value other than 1 on failure.
+ * @remarks
+ * @see
+ * @since
+ */
+int drm_tizen_register_license(const char *pRespBuf, unsigned int respBufLen);
+
+/**
+ * API for checks whether the app drm file or not
+ *
+ * @param[in] pDcfPath File path that to be checked whether the app drm file or not
+ * @param[in] dcfPathLen File path length that to be checked whether the app drm file or not
+ * @return This function returns TADC_SUCCESS(1) on success or an integer value other than 1 on failure.
+ * @remarks
+ * @see
+ * @since
+ */
+int drm_tizen_is_drm_file(const char *pDcfPath, int dcfPathLen);
+
+/**
+ * An application can get decrypted contents(Apps) which is encrypted.
+ *
+ * @param[in] pTADCFilepath TDC DRM File Path
+ * @param[in] tadcFileLen TDC DRM File length
+ * @param[in] pDecryptedFile Decrypted File Path
+ * @param[in] decryptedFileLen Decrypted File length
+ * @return This function returns TADC_SUCCESS(1) on success or an integer value other than 1 on failure.
+ * @remarks
+ * @see
+ * @since
+ */
+//Decrypt DRM File
+int drm_tizen_decrypt_package ( const char *pTADCFilepath, int tadcFileLen, const char *pDecryptedFile, int decryptedFileLen );
+
+/**
+ * An application can request purchase request for getting License.
+ *
+ * @param[in] pTADCFilepath File path of Tizen Apps DRM contents
+ * @param[out] pReqBuf Purchase Request Data
+ * @param[in][out] pReqBufLen IN : pReqBuf Length, OUT : Purchase Request Data String Size ( including null terminator )
+ * @param[out] pLicenseUrl License Acquisition URL Data
+ * @param[in][out] pLicenseUrlLen IN : pLicenseUrl Length, OUT : License Server URL Data String Size ( including null terminator )
+ * @return This function returns TADC_SUCCESS(1) on success or an integer value other than 1 on failure.
+ * @remarks
+ * @see DrmTdcGenerateLicenseRequest
+ * @since
+ */
+int drm_tizen_generate_purchase_request ( const char *pTADCFilepath, char *pReqBuf, unsigned int *pReqBufLen, char *pLicenseUrl, unsigned int *pLicenseUrlLen );
+
+/**
+*@}
+*/ /* Doxygen : addtogroup*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/drm-tizen-error.h b/include/drm-tizen-error.h
new file mode 100644
index 0000000..91f15a0
--- /dev/null
+++ b/include/drm-tizen-error.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 __DRM_TIZEN_ERROR_H__
+#define __DRM_TIZEN_ERROR_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define TADC_SUCCESS 1 // SUCCESS
+// TADC Error Message Define
+#define TADC_GETDUID_ERROR 0x0611 // Get IMEI Error
+#define TADC_GETMCC_ERROR 0x0612 // Get MCC Error
+#define TADC_GETMNC_ERROR 0x0613 // Get MNC Error
+
+#define TADC_REQMAKEHMAC_ERROR 0x0620 // Make Signature Fail in Reauest Message
+#define TADC_RESPONSEMESSAGE_ERROR 0x0621 // Response Message structure Error
+#define TADC_RESPONSESIGNATURE_ERROR 0x0622 // Response Message Signature Error
+
+#define TADC_GETDHKEY_ERROR 0x0630 // Get DH Key Error
+#define TADC_GETRESPONSLICENSE_ERROR 0x0631 // Get License information Error in Response Message
+#define TADC_LICENSEXMLPARSING_ERROR 0x0632 // License XML parsing Error in Response Message
+
+#define TADC_NOTTADCFILE_ERROR 0x0640 // This is not TADC Contents
+#define TADC_CONTENTSVERSION_ERROR 0x0641 // TADC Contents Version Error
+#define TADC_CONTENTSHMAC_ERROR 0x0642 // Contents Signature Error
+#define TADC_CONTENTSXML_ERROR 0x0643 // Contents XML Error in Header
+#define TADC_CONTENTSSTRUCT_ERROR 0X0644 // Contents Header Struct Error
+
+#define TADC_RULE_DUID_ERROR 0x0651 // IMEI Rule check Error
+#define TADC_RULE_MIN_ERROR 0x0652 // MIN Rule check Error
+#define TADC_RULE_NOINFOMATION 0X0653 // NO Information in DB
+
+#define TADC_PARAMETER_ERROR 0X0660 // Input Parameter Error
+#define TADC_XMLPARSER_ERROR 0X0661 // XML Parser Error
+#define TADC_MEMAlOC_ERROR 0x0662 // Memory Alocation Error
+
+#define TADC_CID_NULL_ERROR 0X0670 // CID Null Error
+#define TADC_SID_NULL_ERROR 0X0671 // CID Null Error
+
+//2011.03.08
+#define TADC_RO_SIGNATURE_ERROR 0X0680 // RO Signature Fail
+#define TADC_RO_CERTIFICATE_ERROR 0X0681 // RO Certificate Fail
+
+//2013.03.11
+#define TADC_DHINFO_MAX_ERROR 0x0690 // DHINFO Max error
+#define TADC_GET_ROACQ_INFO_ERROR 0x0691 // TADC_GetROAcqInfo Fail
+#define TADC_MAKE_LICENSEREQ_ERROR 0x0692 // SACD_MakeRequestRO Fail
+#define TADC_GET_HASHREQID_ERROR 0x0693 // TADC_GetHashReqID Fail
+#define TADC_GET_RORES_INFO_ERROR 0x0694 // TADC_GetROAcqInfo Fail
+
+#define TADC_PARSE_TIMECONSTRAINTS_ERROR 0x0695 // DTappsDtTmStr2StrucTm Fail
+#define TADC_LICENSE_INVALID_ERROR 0x0696 // DSaapsValidateConstraints Fail
+
+#define TADC_GET_DEVICEKEY_ERROR 0x0697 // DTappsGetDeviceKey Fail
+#define TADC_GET_BASE64ENCODE_ERROR 0x0698 // DTappsB64Encode Fail
+#define TADC_SET_AES_ENCRYPTKEY_ERROR 0x0699 // DTAPPS_AES_SET_ENCR_KEY Fail
+#define TADC_SET_AES_WRAPKEY_ERROR 0x0700 // DTAPPS_AES_WRAP_KEY Fail
+#define TADC_DB_INSTALL_ERROR 0x0702 // DTapps_DB_Install Fail
+#define TADC_DB_READ_ERROR 0x0703 // DTapps_DB_Install Fail
+
+#define TADC_FILE_OPEN_ERROR 0x0704 //
+#define TADC_FILE_READ_ERROR 0x0705 //
+#define TADC_GET_FILEHEADER_ERROR 0x0706 // DrmTdcGetFileHeader Fail
+#define TADC_GET_CEK_ERROR 0x0707 // DSaapsGetCek Fail
+#define TADC_GET_FILE_HANDLER_ERROR 0x0708
+#define TADC_DECRYPT_PACKAGE_ERROR 0x0709 // DrmTdcDecryptPackage2 Fail
+
+#define TADC_LICENSE_VALID 1
+#define TADC_LICENSE_DB_ERROR 0x802
+#define TADC_LICENSE_NO_LICENSE 0x805
+#define TADC_LICENSE_DUID_MISMATCH 0x806
+#define TADC_LICENSE_UNKNOWN_ERROR 0x807
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __DRM_TIZEN_ERROR_H__
+
diff --git a/include/drm-tizen-mid.h b/include/drm-tizen-mid.h
new file mode 100644
index 0000000..39d6275
--- /dev/null
+++ b/include/drm-tizen-mid.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 drm-tizen-mid.h
+ * @author Sunggun Jung <sunggun.jung@samsung.com>
+ * Kyungwook Tak <k.tak@samsung.com>
+ *
+ */
+
+#ifndef __DRM_TIZEN_MID_H__
+#define __DRM_TIZEN_MID_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <linux/unistd.h>
+#include <unistd.h>
+
+/*Flag to Enable Widget DRM Rights installation using the Linux OMA DRM design */
+//#define __EDRM_ENABLE_WIDGET_DRM__
+#define drmgettid() (long int)syscall(__NR_gettid)
+#define DRM_FILENAME(X) (strrchr((char*)(X), '/') ? (char*)(strrchr((char*)(X), '/') + 1) : ((char*)(X)) )
+
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "DRM_TIZEN"
+
+#include <dlog.h>
+
+/* Tizen Apps DRM related logs */
+#define DRM_TAPPS_LOG(FMT, ARG...) SLOGI(FMT, ##ARG)
+#define DRM_TAPPS_FRQ_LOG(FMT, ARG...) SLOGD(FMT, ##ARG)
+#define DRM_TAPPS_EXCEPTION(FMT, ARG...) SLOGE(FMT, ##ARG)
+#define DRM_TAPPS_SECURE_LOG(FMT, ARG...) SECURE_SLOGI(FMT, ##ARG)
+#define DRM_TAPPS_SECURE_EXCEPTION(FMT, ARG...) SECURE_SLOGE(FMT, ##ARG)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DRM_TIZEN_MID_H__*/
diff --git a/lib/arm/libdrm-service-core-tizen.so.0.2.9 b/lib/arm/libdrm-service-core-tizen.so.0.2.9
deleted file mode 100755
index 8b6bbad..0000000
--- a/lib/arm/libdrm-service-core-tizen.so.0.2.9
+++ /dev/null
Binary files differ
diff --git a/lib/ix86/libdrm-service-core-tizen.so.0.2.9 b/lib/ix86/libdrm-service-core-tizen.so.0.2.9
deleted file mode 100755
index 5652287..0000000
--- a/lib/ix86/libdrm-service-core-tizen.so.0.2.9
+++ /dev/null
Binary files differ
diff --git a/packaging/drm-service-core-tizen.spec b/packaging/drm-service-core-tizen.spec
index 8a82346..97cf07a 100644..100755
--- a/packaging/drm-service-core-tizen.spec
+++ b/packaging/drm-service-core-tizen.spec
@@ -1,67 +1,109 @@
+%define test_build_drm_service_core_tizen 0
+
Name: drm-service-core-tizen
-Summary: The plugin library for installing drm-service-core-tizen.so
-Version: 0.2.9
+Summary: Tizen Application DRM library (Shared Object)
+Version: 0.3.9
Release: 0
-Group: TO_BE/FILLED_IN
-License: Flora
+Group: System/Security
+License: Flora-1.1 and Apache-2.0
Source0: %{name}-%{version}.tar.gz
BuildRequires: cmake
-
-Provides: libdrm-service-core-tizen.so.0
-
-Requires(post): /sbin/ldconfig
-Requires(postun): /sbin/ldconfig
+BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(db-util)
+BuildRequires: pkgconfig(openssl)
+BuildRequires: pkgconfig(cryptsvc)
+BuildRequires: pkgconfig(dukgenerator)
+BuildRequires: pkgconfig(libtzplatform-config)
+Requires: pkgconfig(libtzplatform-config)
%description
-The plugin library for installing drm-service-core-tizen.so
+Description: Tizen Application DRM library (Shared Object)
%package devel
-Summary: The plugin library for drm-service-core-tizen (Development)
-Group: TO_BE/FILLED_IN
+Summary: Tizen Application DRM library (Shared Object)
+Group: Development/Libraries
Requires: %{name} = %{version}-%{release}
%description devel
-The plugin library for installing drm-service-core-tizen.so and header files.
+Description: Tizen Application DRM library (Shared Object)
+
+%if 0%{?test_build_drm_service_core_tizen}
+%package test
+Summary: Tizen Application DRM library (test)
+Group: System/Misc
+Requires: %{name} = %{version}-%{release}
+
+%description test
+Description: Tizen Applicationi DRM library (test)
+%endif
%prep
%setup -q
%build
-%ifarch %{arm}
-cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DARCH=arm
-%else
-cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DARCH=ix86
+MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
+%cmake . -DFULLVER=%{version} \
+ -DMAJORVER=${MAJORVER} \
+%if 0%{?test_build_drm_service_core_tizen}
+ -DBUILD_TEST_DRM_SERVICE_CORE_TIZEN=1 \
%endif
+ -DPREFIX=%{_prefix} \
+ -DEXEC_PREFIX=%{_exec_prefix} \
+ -DLIBDIR=%{_libdir} \
+ -DBINDIR=%{_bindir} \
+ -DINCLUDEDIR=%{_includedir} \
+ -DTZ_SYS_SHARE=%TZ_SYS_SHARE \
+ -DTZ_SYS_BIN=%TZ_SYS_BIN \
+ -DTZ_SYS_DATA=%TZ_SYS_DATA \
+ -DTZ_SYS_ETC=%TZ_SYS_ETC \
+ -DTZ_SYS_RO_WRT_ENGINE=%TZ_SYS_RO_WRT_ENGINE \
+ -DTZ_SYS_DB=%TZ_SYS_DB \
+ -DCMAKE_BUILD_TYPE=%{?build_type:%build_type}%{!?build_type:RELEASE} \
+ -DCMAKE_INSTALL_PREFIX=%{_prefix}
+
make
-#make %{?jobs:-j%jobs}
%install
rm -rf %{buildroot}
-
+mkdir -p %{buildroot}%{TZ_SYS_SHARE}/license/%{name}
+cp %{_builddir}/%{name}-%{version}/LICENSE.* %{buildroot}%{TZ_SYS_SHARE}/license/%{name}
%make_install
%post
/bin/rm -f /etc/ld.so.cache
/sbin/ldconfig
-
%{_bindir}/drm_tizen_initialize
-
-ln -s -f %{_libdir}/libdrm-service-core-tizen.so.0.2.9 %{_libdir}/libdrm-service-core-tizen.so.0
-ln -s -f %{_libdir}/libdrm-service-core-tizen.so.0 %{_libdir}/libdrm-service-core-tizen.so
+chsmack -a "org.tizen.tsefl" %{TZ_SYS_DB}/.dtapps.db*
+chown :5000 %{TZ_SYS_DB}/.dtapps.db*
+chmod 660 %{TZ_SYS_DB}/.dtapps.db*
%postun -p /sbin/ldconfig
+%clean
+rm -rf %{buildroot}
+
%files
%manifest drm-service-core-tizen.manifest
%defattr(-,root,root,-)
%{_libdir}/libdrm-service-core-tizen.so*
%{_bindir}/drm_tizen_initialize
+%{TZ_SYS_SHARE}/license/%{name}/*
+%{TZ_SYS_SHARE}/tizen_app_drm/root_certs/ro_root_cert.pem
%files devel
%defattr(-,root,root,-)
%{_libdir}/pkgconfig/drm-service-core-tizen.pc
-%{_includedir}/drm-tizen/drm-oem-sapps.h
-
-%clean
-rm -rf drm_tizen_initialize
-rm -rf libdrm-service-core-tizen.so*
+%{_includedir}/drm-tizen/drm-tizen-apps.h
+%{_includedir}/drm-tizen/drm-tizen-error.h
+%exclude %{_includedir}/drm-tizen/drm-tizen-mid.h
+
+%if 0%{?test_build_drm_service_core_tizen}
+%files test
+#%defattr(-,root,root,-)
+%{_bindir}/drm_test_tizen
+%{TZ_SYS_DATA}/drm_test/RO/*
+%{TZ_SYS_DATA}/drm_test/DCF/*
+%{TZ_SYS_DATA}/drm_test/DecryptedApp/*
+%{TZ_SYS_DATA}/drm_test/Key/*
+%{TZ_SYS_SHARE}/tizen_app_drm/root_certs/ro_test_root_ca.pem
+%endif
diff --git a/resource/ro_root_cert.pem b/resource/ro_root_cert.pem
new file mode 100644
index 0000000..cc4c462
--- /dev/null
+++ b/resource/ro_root_cert.pem
@@ -0,0 +1,27 @@
+-----BEGIN CERTIFICATE-----
+MIIEhjCCA26gAwIBAgIJANfJ9Z8/G/FiMA0GCSqGSIb3DQEBBQUAMIGIMQswCQYD
+VQQGEwJLUjEcMBoGA1UEChMTU2Ftc3VuZyBFbGVjdHJvbmljczEuMCwGA1UECxMl
+U2Ftc3VuZyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgQ2VudHJhbDErMCkGA1UEAxMi
+U2Ftc3VuZyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0wOTExMDIwMjUz
+MTBaFw0zNzAzMjAwMjUzMTBaMIGIMQswCQYDVQQGEwJLUjEcMBoGA1UEChMTU2Ft
+c3VuZyBFbGVjdHJvbmljczEuMCwGA1UECxMlU2Ftc3VuZyBDZXJ0aWZpY2F0ZSBB
+dXRob3JpdHkgQ2VudHJhbDErMCkGA1UEAxMiU2Ftc3VuZyBSb290IENlcnRpZmlj
+YXRlIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL6o
+/Gb8s6Od9tp7kQFMnitPghpflaK8aRrAe9ac0+X/ZfVksSWMXnoeS8+heegwQJqU
+Lxh3JTWqE/1t3jTj9fdlaad8wfqTqzPWBF1gB0xZrSyIuamHk3I32Wva9ij7FY2a
+I6nz1PCI1eG3UYISDRFNxBqRJfraX7akgnpnuG5fndEEtOabmKzRtFCSgGTXhyng
+N7efuGW9M60aSOd4ST21BtkIcrM/Go3kwIz6/tIg9MtuB8SVvzlvAiLZUygywMpu
+Z/wqwans938c+329F8DLcnIKOJ+Nit0u/462+6VJYPKVlmewAn6sjp6hnSk2Od+u
+6NUxlXLlsCrDzn5gFCECAwEAAaOB8DCB7TAdBgNVHQ4EFgQUdSvSt/cYuTKeXokz
+T+hjkv6fjVYwgb0GA1UdIwSBtTCBsoAUdSvSt/cYuTKeXokzT+hjkv6fjVahgY6k
+gYswgYgxCzAJBgNVBAYTAktSMRwwGgYDVQQKExNTYW1zdW5nIEVsZWN0cm9uaWNz
+MS4wLAYDVQQLEyVTYW1zdW5nIENlcnRpZmljYXRlIEF1dGhvcml0eSBDZW50cmFs
+MSswKQYDVQQDEyJTYW1zdW5nIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5ggkA
+18n1nz8b8WIwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEADiz0SbgC
+pHolQ7VqnKNH/zBHKU7yotq+ouZDJ+2JmZHpr8s811/K5EgDFoHJXyH6aKUj+iie
+ZDZe/t3LENHUC0X7O210l8PixxPjEUtYncOCoEfr4Ox0zjhTQAvNV8wY0NhGxZkv
+4+XdJXyGWvL3zZC6qU347S3eaSseCgqWFtOY6vAnKQbppEVVEAbcMB755egYCNBx
+qt/phXfoeL3JBN/faG/Rfg4EM67b7zlrMqMC1w8Q8uq2Ac5jRAWsTHSTezQgJs9/
+uTb298P9/AYzm/jBgLT5hjZvzGR6zie3yDMudvvIeR7OmoJBDAj2knngcxUMY6w5
+nvdwrzzTEwZx/A==
+-----END CERTIFICATE-----
diff --git a/service/drm-tapps-initialize.cpp b/service/drm-tapps-initialize.cpp
new file mode 100644
index 0000000..2d0952e
--- /dev/null
+++ b/service/drm-tapps-initialize.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 <drm-tizen-mid.h>
+
+#include "DTapps2SqliteDB.h"
+
+static int __drm_tad_create_db(void)
+{
+ BOOL db_ret = FALSE;
+ int IsBeginSuccessful = 0;
+
+ char Table_Name[16] = "dtapps2rights";
+ char* sql_query_table = NULL;
+ void *pDb = NULL;
+
+ db_ret = DTappsDBOpen(pDb, __func__);
+
+ if(db_ret != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("DTappsDBOpen FAILED");
+
+ return -1;
+ }
+
+ db_ret = DTappsDBBeginImmedTrans(__func__);
+
+ if(db_ret != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("DTappsDBBeginImmedTrans FAILED");
+
+ goto ErrorExit;
+ }
+
+ IsBeginSuccessful = 1;
+
+ sql_query_table = DTappsGetSQLCreateTable(Table_Name);
+
+ if(sql_query_table == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("DTappsGetSQLCreateTable FAILED");
+
+ goto ErrorExit;
+ }
+
+ DRM_TAPPS_FRQ_LOG("sql_query_table = %s", sql_query_table);
+
+ db_ret = DTappsExecuteSQL(pDb, sql_query_table);
+
+ if(db_ret != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("DTappsGetSQLCreateTable FAILED");
+
+ goto ErrorExit;
+ }
+
+ db_ret = DTappsDBCommit(__func__);
+
+ if(db_ret != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("DTappsDBCommit FAILED");
+
+ goto ErrorExit;
+ }
+
+ db_ret = DTappsDBClose(__func__);
+
+ if(db_ret != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("DTappsDBClose FAILED");
+
+ goto ErrorExit;
+ }
+
+ DRM_TAPPS_FRQ_LOG("TAD DB created successfully");
+
+ return 0;
+
+ErrorExit:
+
+ if (1 == IsBeginSuccessful)
+ {
+ DTappsDBRollback(__func__);
+ }
+
+ db_ret = DTappsDBClose(__func__);
+ if(db_ret != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("DTappsDBClose FAILED");
+ }
+
+ DRM_TAPPS_EXCEPTION("TAD DB creation FAILED");
+
+ return -1;
+}
+
+int main(int argc, char* argv[])
+{
+ DRM_TAPPS_FRQ_LOG("=============Start Create TAD DB file ================\n\n ");
+
+ if(0 != __drm_tad_create_db())
+ {
+ DRM_TAPPS_EXCEPTION("=============Error Creating TAD DB file ================\n\n ");
+
+ return 1;
+ }
+
+ DRM_TAPPS_FRQ_LOG("=============Success Created TAD DB file ================\n\n ");
+
+ return 0;
+}
diff --git a/service/drm-tapps.cpp b/service/drm-tapps.cpp
new file mode 100644
index 0000000..2cc8c5e
--- /dev/null
+++ b/service/drm-tapps.cpp
@@ -0,0 +1,428 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 drm-tapps.cpp
+ * @author Sunggun Jung <sunggun.jung@samsung.com>
+ *
+ */
+
+#include "TADC_Core.h"
+#include "TADC_IF.h"
+
+#include "DrmTdcSvc.h"
+#include "drm-tizen-mid.h"
+#include "drm-tizen-apps.h"
+#include "drm-tizen-error.h"
+
+#include "DTapps2SqliteDB.h"
+#include "DTapps2Base64.h"
+#include "DTapps2HMAC.h"
+#include "DTapps2Rights.h"
+
+/* Enable this flag to take API level time profiling */
+//#define __DRM_TAPPS_API_TIME_PROFILING__
+
+#ifdef __DRM_TAPPS_API_TIME_PROFILING__
+#include <sys/time.h>
+
+class DrmTappsProf
+{
+public:
+ DrmTappsProf(const char* function);
+ ~DrmTappsProf();
+ struct timeval TappsStartTv;
+ struct timeval TappsStopTv;
+ char TappsfunNane[256];
+};
+
+DrmTappsProf::DrmTappsProf(const char* function)
+{
+ memcpy(TappsfunNane, function, strlen(function));
+ gettimeofday(&TappsStartTv, NULL);
+ DRM_TAPPS_EXCEPTION("[DRM-TIZEN-PERF]START:SEC=%ld, USEC=%ld for [%s]",(long int)(TappsStartTv.tv_sec) , (long int)(TappsStartTv.tv_usec),function);
+}
+
+DrmTappsProf::~DrmTappsProf()
+{
+ gettimeofday(&TappsStopTv, NULL);
+ DRM_TAPPS_EXCEPTION("[DRM-TIZEN-PERF] STOP:SEC=%ld, USEC=%ld for [%s]", (long int)(TappsStopTv.tv_sec), (long int)(TappsStopTv.tv_usec),TappsfunNane);
+ DRM_TAPPS_EXCEPTION("[DRM-TIZEN-PERF]TOTAL_DIFFF : USEC=%ld for [%s]", ((long int)(TappsStopTv.tv_sec - TappsStartTv.tv_sec) * (1000000) + (long int)(TappsStopTv.tv_usec - TappsStartTv.tv_usec)), TappsfunNane);
+}
+
+#define DRM_TAPPS_API_TIME() DrmTappsProf DrmTappsObj(__func__);
+#else
+#define DRM_TAPPS_API_TIME()
+#endif /* __DRM_TAPPS_API_TIME_PROFILING__ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Define EXPORT_API */
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+int _drm_tapps_generate_purchase_request(const char *pTADCFilepath, char *pReqBuf, unsigned int *pReqBufLen, char *pLicenseUrl, unsigned int *pLicenseUrlLen);
+int _drm_tapps_generate_license_request(const char *pRespBuf, unsigned int respBufLen, char *pReqBuf, unsigned int *pReqBufLen, char *pLicenseUrl, unsigned int *pLicenseUrlLen);
+int _drm_tapps_register_license(const char *pRespBuf, unsigned int respBufLen);
+int _drm_tapps_decrypt_package(const char *pTADCFilepath, int stadFileLen, const char *pDecryptedFile, int decryptedFileLen);
+int _drm_tapps_is_drm_file(const char *pDcfPath, int dcfPathLen);
+
+EXPORT_API int drm_tizen_generate_license_request
+(
+ const char *pRespBuf, //Response Data String of the Purchase Request ( Null terminator string )
+ unsigned int respBufLen, //pResBuf Length
+ char *pReqBuf, //License Request Data
+ unsigned int *pReqBufLen, //IN : pReqBuf Length, OUT : Rights Request Data String Size ( including null terminator )
+ char *pLicenseUrl, //License Acquisition URL Data
+ unsigned int *pLicenseUrlLen //IN : pLicenseUrl Length, OUT : Rights Issuer Server URL Data String Size ( including null terminator )
+)
+{
+ int ret = TADC_SUCCESS;
+ DRM_TAPPS_LOG("%s starts", __func__);
+
+ if (pRespBuf == NULL || pReqBuf == NULL || pLicenseUrl == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("%s) Error : Parameters NULL.", __func__);
+ return TADC_PARAMETER_ERROR;
+ }
+
+ if (strlen(pRespBuf) != respBufLen)
+ {
+ DRM_TAPPS_EXCEPTION("%s) Error : Input value and size weren't equal.", __func__);
+ return TADC_PARAMETER_ERROR;
+ }
+
+ ret = _drm_tapps_generate_license_request(pRespBuf, respBufLen, pReqBuf, pReqBufLen, pLicenseUrl, pLicenseUrlLen);
+ DRM_TAPPS_LOG("%s result=%x", __func__, ret);
+
+ return ret;
+}
+
+int _drm_tapps_generate_license_request
+(
+ const char *pRespBuf, //Response Data String of the Purchase Request ( Null terminator string )
+ unsigned int respBufLen, //pResBuf Length
+ char *pReqBuf, //License Request Data
+ unsigned int *pReqBufLen, //IN : pReqBuf Length, OUT : Rights Request Data String Size ( including null terminator )
+ char *pLicenseUrl, //License Acquisition URL Data
+ unsigned int *pLicenseUrlLen//IN : pLicenseUrl Length, OUT : Rights Issuer Server URL Data String Size ( including null terminator )
+)
+{
+ int ret = TADC_SUCCESS;
+ DRM_TAPPS_LOG("%s starts", __func__);
+
+ if (pRespBuf == NULL || pReqBuf == NULL || pLicenseUrl == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("%s) Error : Parameters NULL.", __func__);
+ return TADC_PARAMETER_ERROR;
+ }
+
+ if (strlen(pRespBuf) != respBufLen)
+ {
+ DRM_TAPPS_EXCEPTION("%s) Error : Input value and size weren't equal.", __func__);
+ return TADC_PARAMETER_ERROR;
+ }
+
+ ret = DrmTdcGenerateLicenseRequest( pRespBuf, respBufLen, pReqBuf, pReqBufLen, pLicenseUrl, pLicenseUrlLen );
+ DRM_TAPPS_LOG("%s result = %x", __func__, ret);
+
+ return ret;
+}
+
+EXPORT_API int drm_tizen_register_license
+(
+ const char *pRespBuf, //Response Data String of the Rights Request ( Null terminator string )
+ unsigned int respBufLen //pResBuf Length
+)
+{
+ int ret = TADC_SUCCESS;
+ DRM_TAPPS_LOG("%s starts", __func__);
+
+ if (pRespBuf == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("%s) Parameters NULL!", __func__);
+ return TADC_PARAMETER_ERROR;
+ }
+
+ if (strlen(pRespBuf) != respBufLen)
+ {
+ DRM_TAPPS_EXCEPTION("%s) Input value and size wasn't equal.", __func__);
+ return TADC_PARAMETER_ERROR;
+ }
+
+ ret = _drm_tapps_register_license(pRespBuf, respBufLen);
+ DRM_TAPPS_LOG("%s result=%x", __func__, ret);
+
+ return ret;
+}
+
+int _drm_tapps_register_license
+(
+ const char *pRespBuf, //Response Data String of the Rights Request ( Null terminator string )
+ unsigned int respBufLen //pResBuf Length
+)
+{
+ DRM_TAPPS_API_TIME()
+
+ int Ret = TADC_SUCCESS;
+ char pDecLicenseBuf[1024*8] = {0, };
+ unsigned int decLicenseBufLen = 0;
+
+ DRM_TAPPS_LOG("%s starts", __func__);
+
+ if(pRespBuf == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("%s) Parameters NULL!", __func__);
+ return TADC_PARAMETER_ERROR;
+ }
+
+ if (strlen(pRespBuf) != respBufLen)
+ {
+ DRM_TAPPS_EXCEPTION("%s) Input value and size weren't equal.", __func__);
+ return TADC_PARAMETER_ERROR;
+ }
+
+ memset(pDecLicenseBuf, 0x00, sizeof(pDecLicenseBuf));
+ decLicenseBufLen = sizeof(pDecLicenseBuf);
+
+ /* Has to be enabled when the response from server is known which will be encrypted!! */
+ Ret = DrmTdcDecryptLicense(pRespBuf, respBufLen, pDecLicenseBuf, &decLicenseBufLen);
+ if (Ret != TADC_SUCCESS)
+ {
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptLicense failed!!! Ret = %x",Ret);
+ return Ret;
+ }
+
+ Ret = DTappsInstallLicense(pDecLicenseBuf);
+ if (Ret != TADC_SUCCESS)
+ {
+ DRM_TAPPS_EXCEPTION("DTappsInstallLicense failed!!! Ret = %x", Ret);
+ goto DTAPPS_EXIT;
+ }
+
+ DRM_TAPPS_LOG("%s result = %x", __func__, Ret);
+
+DTAPPS_EXIT:
+ return Ret;
+}
+
+
+EXPORT_API int drm_tizen_is_drm_file(const char *pDcfPath, int dcfPathLen)
+{
+ int ret = TADC_SUCCESS;
+
+ DRM_TAPPS_LOG("%s starts", __func__);
+ if (pDcfPath == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("%s) Parameters NULL!", __func__);
+ return TADC_PARAMETER_ERROR;
+ }
+
+ if ((int)strlen(pDcfPath) != dcfPathLen)
+ {
+ DRM_TAPPS_EXCEPTION("%s) Input value and size wasn't equal.", __func__);
+ return TADC_PARAMETER_ERROR;
+ }
+
+ DRM_TAPPS_LOG("_drm_tizen_is_drm_file = %s started!", pDcfPath);
+
+ ret = _drm_tapps_is_drm_file(pDcfPath, dcfPathLen);
+ DRM_TAPPS_LOG("%s result=%x", __func__, ret);
+
+ return ret;
+}
+
+int _drm_tapps_is_drm_file(const char *pDcfPath, int dcfPathLen)
+{
+ DRM_TAPPS_API_TIME()
+
+ int ret = TADC_SUCCESS;
+ bool bRet = FALSE;
+ DrmTdcFileHeader fileHeader;
+
+ DRM_TAPPS_LOG("%s starts", __func__);
+ if (pDcfPath == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("%s) Parameters NULL!", __func__);
+ ret = TADC_PARAMETER_ERROR;
+ goto finish;
+ }
+
+ if ((int)strlen(pDcfPath) != dcfPathLen)
+ {
+ DRM_TAPPS_EXCEPTION("%s) Input value and size wasn't equal.", __func__);
+ ret = TADC_PARAMETER_ERROR;
+ goto finish;
+ }
+
+ memset(&fileHeader, 0, sizeof(DrmTdcFileHeader));
+ bRet = DrmTdcGetFileHeader(pDcfPath, &fileHeader);
+ if (bRet == FALSE)
+ {
+ DRM_TAPPS_EXCEPTION("%s Error : DrmTdcGetFileHeader is failed", __func__);
+ ret = TADC_NOTTADCFILE_ERROR;
+ }
+
+ DRM_TAPPS_LOG("%s result = %x", __func__, ret);
+
+finish:
+ return ret;
+}
+
+EXPORT_API int drm_tizen_decrypt_package(
+ const char *pTADCFilepath, /* TDC DRM File Path */
+ int stadFileLen,
+ const char *pDecryptedFile, /* Decrypted File Path */
+ int decryptedFileLen
+)
+{
+ int ret = TADC_SUCCESS;
+ DRM_TAPPS_LOG("drm_tizen_decrypt_package(%s, %s) started!", pTADCFilepath, pDecryptedFile);
+
+ ret = _drm_tapps_decrypt_package(pTADCFilepath, stadFileLen, pDecryptedFile, decryptedFileLen);
+ DRM_TAPPS_LOG("%s result=%x", __func__, ret);
+
+ return ret;
+}
+
+int _drm_tapps_decrypt_package
+(
+ const char *pTADCFilepath, //TDC DRM File Path
+ int stadFileLen,
+ const char *pDecryptedFile, //Decrypted File Path
+ int decryptedFileLen
+)
+{
+ DRM_TAPPS_API_TIME()
+
+ bool bRet = true;
+ int ret = TADC_SUCCESS;
+
+ T_RO t_RO = {0,};
+ DrmTdcFileHeader fileHeader = {{0}};
+
+ DRM_TAPPS_LOG("%s starts", __func__);
+ if (pTADCFilepath == NULL || pDecryptedFile == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("%s) Parameters NULL!", __func__);
+ return TADC_PARAMETER_ERROR;
+ }
+
+ if (((int)strlen(pTADCFilepath) != stadFileLen ) || ((int)strlen(pDecryptedFile) != decryptedFileLen))
+ {
+ DRM_TAPPS_EXCEPTION("%s) Input value and size wasn't equal.", __func__);
+ return TADC_PARAMETER_ERROR;
+ }
+ DRM_TAPPS_SECURE_LOG("%s) TADC File Path=%s, Decrypted File Path=%s", __func__, pTADCFilepath, pDecryptedFile);
+
+ bRet = DrmTdcGetFileHeader(pTADCFilepath, &fileHeader);
+ if (FALSE == bRet)
+ {
+ DRM_TAPPS_EXCEPTION("DrmTdcGetFileHeader failed!!");
+ ret = TADC_GET_FILEHEADER_ERROR;
+ goto TAPPS_END;
+ }
+ DRM_TAPPS_LOG("pTADCFilepath=%s, fileHeader.cid=%s, fileHeader.riurl=%s", pTADCFilepath, fileHeader.cid, fileHeader.riurl);
+
+ bRet = DTappsGetCEK(fileHeader.cid,&t_RO);
+ if(FALSE == bRet)
+ {
+ DRM_TAPPS_EXCEPTION("DTappsGetCEK failed!! pTADCFilepath=%s, fileHeader.cid=%s", pTADCFilepath, fileHeader.cid);
+ ret = TADC_GET_CEK_ERROR;
+ goto TAPPS_END;
+ }
+ DRM_TAPPS_SECURE_LOG("fileHeader.cid=%s, t_RO.t_Content.CEK=%s", fileHeader.cid, t_RO.t_Content.CEK);
+
+ bRet = DrmTdcDecryptPackage2(pTADCFilepath, t_RO, pDecryptedFile);
+ if(FALSE == bRet)
+ {
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptPackage2 failed!!, pTADCFilepath=%s, pDecryptedFile=%s",pTADCFilepath,pDecryptedFile);
+ ret = TADC_DECRYPT_PACKAGE_ERROR;
+ goto TAPPS_END;
+ }
+
+TAPPS_END:
+ if (t_RO.t_Content.CID)
+ {
+ DTAPPS_FREE(t_RO.t_Content.CID);
+ }
+ if (t_RO.t_Content.CEK)
+ {
+ DTAPPS_FREE(t_RO.t_Content.CEK);
+ }
+ if ((t_RO.PerFlag & DUID_RULE) && (t_RO.t_Permission.t_Individual.DUID))
+ {
+ DTAPPS_FREE(t_RO.t_Permission.t_Individual.DUID);
+ }
+ if (bRet == FALSE)
+ {
+ DRM_TAPPS_EXCEPTION("%s failed!! pTADCFilepath=%s, pDecryptedFile=%s", __func__, pTADCFilepath, pDecryptedFile);
+ return ret;
+ }
+ else
+ {
+ DRM_TAPPS_LOG("%s Success!!", __func__);
+ return ret;
+ }
+}
+
+EXPORT_API int drm_tizen_generate_purchase_request
+(
+ const char *pTADCFilepath, //TDC DRM File Path
+ char *pReqBuf, //Purchase Request Data
+ unsigned int *pReqBufLen, //IN : pReqBuf Length, OUT : Purchase Request Data String Size ( including null terminator )
+ char *pLicenseUrl, //License Acquisition URL Data
+ unsigned int *pLicenseUrlLen //IN : pLicenseUrl Length, OUT : License Server URL Data String Size ( including null terminator )
+)
+{
+ DRM_TAPPS_LOG("%s started!", __func__);
+
+ return _drm_tapps_generate_purchase_request(pTADCFilepath,
+ pReqBuf,
+ pReqBufLen,
+ pLicenseUrl,
+ pLicenseUrlLen);
+}
+
+int _drm_tapps_generate_purchase_request
+(
+ const char *pTADCFilepath, //TDC DRM File Path
+ char *pReqBuf, //Purchase Request Data
+ unsigned int *pReqBufLen, //IN : pReqBuf Length, OUT : Purchase Request Data String Size ( including null terminator )
+ char *pLicenseUrl, //License Acquisition URL Data
+ unsigned int *pLicenseUrlLen //IN : pLicenseUrl Length, OUT : License Server URL Data String Size ( including null terminator )
+)
+{
+ DRM_TAPPS_API_TIME()
+
+ bool bRet = FALSE;
+
+ DRM_TAPPS_LOG("%s starts", __func__);
+ bRet = DrmTdcGeneratePurchaseRequest(pTADCFilepath, pReqBuf, pReqBufLen, pLicenseUrl, pLicenseUrlLen);
+ if (bRet == FALSE)
+ {
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/tadcore/DrmFileHandleMgr/DrmFileApi.cpp b/tadcore/DrmFileHandleMgr/DrmFileApi.cpp
new file mode 100644
index 0000000..0746450
--- /dev/null
+++ b/tadcore/DrmFileHandleMgr/DrmFileApi.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 "DrmFileMgr.h"
+#include "TADC_ErrorCode.h"
+#include "drm_intf_tapps.h"
+
+EXPORT_API
+int DrmTdcFileOpen(const char* filePath, int mode, int* handle)
+{
+ int nRet = TADC_SUCCESS;
+ int key = 0;
+
+ DrmFileMgr* pDrmFileMgr = NULL;
+
+ if (filePath == NULL || strlen(filePath) < 1)
+ {
+ DRM_TAPPS_EXCEPTION("Parameter error!");
+ return TADC_PARAMETER_ERROR;
+ }
+
+ pDrmFileMgr = DrmFileMgr::GetInstance();
+ if (pDrmFileMgr == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("DrmFileMgr::GetInstance() error!");
+ return TADC_GET_FILE_HANDLER_ERROR;
+ }
+
+ nRet = pDrmFileMgr->OpenFileHandler(filePath, 1, &key);
+ if (nRet != TADC_SUCCESS)
+ {
+ DRM_TAPPS_EXCEPTION("DrmFileMgr::OpenFileHandler() error!");
+ return nRet;
+ }
+
+ *handle = key;
+
+ return nRet;
+}
+
+EXPORT_API
+int DrmTdcFileClose(int* handle)
+{
+ int nRet = TADC_SUCCESS;
+ int key = *handle;
+
+ DrmFileMgr *pDrmFileMgr = DrmFileMgr::GetInstance();
+ if (pDrmFileMgr == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("DrmFileMgr::GetInstance() error!");
+ return TADC_GET_FILE_HANDLER_ERROR;
+ }
+
+ nRet = pDrmFileMgr->CloseFileHandler(key);
+ if (nRet != TADC_SUCCESS)
+ {
+ DRM_TAPPS_EXCEPTION("DrmFileMgr::OpenFileHandler() error!");
+ return nRet;
+ }
+
+ return nRet;
+}
+
+EXPORT_API
+int DrmTdcFileRead(int* handle, void* pBuf, long long bufLen, long long* pReadLen)
+{
+ int nRet = TADC_SUCCESS;
+ int key = *handle;
+
+ DrmFileMgr* pDrmFileMgr = NULL;
+ DrmFileHandler* pDrmFileHandler = NULL;
+
+ pDrmFileMgr = DrmFileMgr::GetInstance();
+ if (pDrmFileMgr == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("DrmFileMgr::GetInstance() error!");
+ return TADC_GET_FILE_HANDLER_ERROR;
+ }
+
+ nRet = pDrmFileMgr->GetFileHandler(key, &pDrmFileHandler);
+ if (nRet != TADC_SUCCESS)
+ {
+ DRM_TAPPS_EXCEPTION("DrmFileMgr::GetFileHandler() error!");
+ return nRet;
+ }
+
+ nRet = pDrmFileHandler->DrmRead(pBuf, bufLen, pReadLen);
+ if (nRet != TADC_SUCCESS)
+ {
+ DRM_TAPPS_EXCEPTION("DrmFileMgr::DrmRead() error!");
+ return nRet;
+ }
+ return nRet;
+}
+
+EXPORT_API
+int DrmTdcFileTell(int* handle, long long *position)
+{
+ int nRet = TADC_SUCCESS;
+ int key = *handle;
+ long long offset = 0;
+
+ DrmFileMgr* pDrmFileMgr = NULL;
+ DrmFileHandler* pDrmFileHandler = NULL;
+
+ pDrmFileMgr = DrmFileMgr::GetInstance();
+ if (pDrmFileMgr == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("DrmFileMgr::GetInstance() error!");
+ return TADC_GET_FILE_HANDLER_ERROR;
+ }
+
+ nRet = pDrmFileMgr->GetFileHandler(key, &pDrmFileHandler);
+ if (nRet != TADC_SUCCESS)
+ {
+ DRM_TAPPS_EXCEPTION("DrmFileMgr::GetFileHandler() error!");
+ return nRet;
+ }
+
+ offset = pDrmFileHandler->DrmTell();
+
+ *position = offset;
+
+ return nRet;
+}
+
+EXPORT_API
+int DrmTdcFileSeek(int* handle, long long offset, int origin)
+{
+ int nRet = TADC_SUCCESS;
+ int key = *handle;
+
+ DrmFileMgr* pDrmFileMgr = NULL;
+ DrmFileHandler* pDrmFileHandler = NULL;
+
+ pDrmFileMgr = DrmFileMgr::GetInstance();
+ if (pDrmFileMgr == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("DrmFileMgr::GetInstance() error!");
+ return TADC_GET_FILE_HANDLER_ERROR;
+ }
+
+ nRet = pDrmFileMgr->GetFileHandler(key, &pDrmFileHandler);
+ if (nRet != TADC_SUCCESS)
+ {
+ DRM_TAPPS_EXCEPTION("DrmFileMgr::GetFileHandler() error!");
+ return nRet;
+ }
+
+ nRet = pDrmFileHandler->DrmSeek(offset, origin);
+ if (nRet != TADC_SUCCESS)
+ {
+ DRM_TAPPS_EXCEPTION("DrmFileHandler::DrmSeek() error!");
+ return nRet;
+ }
+
+ return nRet;
+}
diff --git a/tadcore/DrmFileHandleMgr/DrmFileHandler.cpp b/tadcore/DrmFileHandleMgr/DrmFileHandler.cpp
new file mode 100644
index 0000000..e1a5a57
--- /dev/null
+++ b/tadcore/DrmFileHandleMgr/DrmFileHandler.cpp
@@ -0,0 +1,503 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 "TADC_Core.h"
+#include "TADC_ErrorCode.h"
+#include "DTapps2Rights.h"
+#include "DrmFileHandler.h"
+#include "TADC_IF.h"
+
+
+
+
+#define TDC_DECRYPT_BLOCKSIZE 512
+
+DrmFileHandler::DrmFileHandler(void)
+ : m_pFilePath(NULL)
+ , m_pCID(NULL)
+ , m_pCEK(NULL)
+ , m_pFP(NULL)
+{
+}
+
+DrmFileHandler::~DrmFileHandler(void)
+{
+ if (m_pFilePath != NULL)
+ {
+ delete[] m_pFilePath;
+ }
+
+ if (m_pCID != NULL)
+ {
+ delete[] m_pCID;
+ }
+
+ if (m_pCEK != NULL)
+ {
+ delete[] m_pCEK;
+ }
+
+ if (m_pDecBuf != NULL)
+ {
+ delete[] m_pDecBuf;
+ }
+
+ if (m_pFP != NULL)
+ {
+ fclose(m_pFP);
+ }
+}
+
+int DrmFileHandler::Construct(const char* szDrmFilePath)
+{
+ T_FILE_HEADER t_FileHeader;
+ T_DRM_HEADER t_DRMHeader;
+ T_RO t_RO;
+
+ int ret = TADC_SUCCESS;
+ bool bRet = true;
+
+ // 1. Check the file is TADC DRM file.
+ memset(&t_FileHeader, 0x00, sizeof(t_FileHeader));
+ memset(&t_DRMHeader, 0x00, sizeof(T_DRM_HEADER));
+ memset(&t_RO, 0x00, sizeof(T_RO));
+
+ DRM_TAPPS_LOG("%s starts", __func__);
+
+ if (szDrmFilePath == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("Parameters NULL!");
+ ret = TADC_PARAMETER_ERROR;
+
+ goto finish;
+ }
+
+ ret = TADC_GetDRMHeaderFromFile(szDrmFilePath, &t_FileHeader, &t_DRMHeader);
+
+ if (ret < 0)
+ {
+ DRM_TAPPS_EXCEPTION("Error : TADC_GetDRMHeaderFromFile() - %s TADC Error Code - %d", szDrmFilePath, ret);
+ ret = TADC_NOTTADCFILE_ERROR;
+
+ goto finish;
+ }
+
+ // 2. Validate license and get the CEK for the DRM file
+ bRet = DTappsGetCEK((char*)t_DRMHeader.CID, &t_RO);
+ if (bRet == false)
+ {
+ DRM_TAPPS_EXCEPTION("Error : DTappsGetCEK() - %s", t_DRMHeader.CID);
+ ret = TADC_GET_CEK_ERROR;
+
+ goto finish;
+ }
+
+ // 3. Setting the member variable
+ m_pFilePath = new unsigned char[strlen(szDrmFilePath) + 1];
+ memset(m_pFilePath, 0x00, strlen(szDrmFilePath) + 1);
+ memcpy(m_pFilePath, szDrmFilePath, strlen(szDrmFilePath));
+
+ m_pCID = new unsigned char[strlen((char*)t_DRMHeader.CID) + 1];
+ memset(m_pCID, 0x00, strlen((char*)t_DRMHeader.CID) + 1);
+ memcpy(m_pCID, t_DRMHeader.CID, strlen((char*)t_DRMHeader.CID));
+
+ m_pCEK = new unsigned char[CEK_SIZE + 1];
+ memset(m_pCEK, 0x00, CEK_SIZE + 1);
+ memcpy(m_pCEK, t_RO.t_Content.CEK, CEK_SIZE);
+
+ m_encryptionLevel = t_DRMHeader.EncryptionLevel;
+ m_encryptionRange = t_DRMHeader.EncryptionRange;
+ m_plaintextSize = t_DRMHeader.PlaintextSize;
+
+ // 4. Open the DRM file and set the filepointer to member variable
+ m_pFP = fopen(szDrmFilePath, "rb");
+ if (m_pFP == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("Error : fopen() - %s", szDrmFilePath);
+ ret = TADC_FILE_OPEN_ERROR;
+
+ goto finish;
+ }
+
+ m_PlaintextStartOffset = t_FileHeader.Offset1 + 35 + t_DRMHeader.XmlSize;
+
+ fseek(m_pFP, 0, SEEK_END);
+ m_OriginEndOffset = ftell(m_pFP);
+
+ m_plaintextSize = m_OriginEndOffset - m_PlaintextStartOffset;
+ if (m_plaintextSize != t_DRMHeader.PlaintextSize)
+ {
+ DRM_TAPPS_EXCEPTION("Error : plaintext file size incorrect. real = %ld, header = %ld", m_plaintextSize, t_DRMHeader.PlaintextSize);
+ ret = TADC_FILE_OPEN_ERROR;
+
+ goto finish;
+ }
+
+ m_DrmEndOffset = m_plaintextSize;
+
+ fseek(m_pFP, m_PlaintextStartOffset, SEEK_SET);
+ m_OriginCurOffset = ftell(m_pFP);
+ m_DrmCurOffset = 0;
+
+ m_blockCnt = (m_plaintextSize / 512) + ((m_plaintextSize % 512) ? 1 : 0);
+
+ m_curBlockIndex = 0;
+ m_decReadlen = 0;
+
+ DRM_TAPPS_LOG("m_pCEK = %s", m_pCEK);
+ DRM_TAPPS_LOG("m_pCID = %s", m_pCID);
+ DRM_TAPPS_LOG("m_pFilePath = %s", m_pFilePath);
+
+ DRM_TAPPS_LOG("m_encryptionLevel = %ld", m_encryptionLevel);
+ DRM_TAPPS_LOG("m_encryptionRange = %ld", m_encryptionRange);
+ DRM_TAPPS_LOG("m_plaintextSize = %ld", m_plaintextSize);
+
+ DRM_TAPPS_LOG("m_PlaintextStartOffset = %ld", m_PlaintextStartOffset);
+ DRM_TAPPS_LOG("m_OriginEndOffset = %ld", m_OriginEndOffset);
+
+ DRM_TAPPS_LOG("m_OriginCurOffset = %ld", m_OriginCurOffset);
+ DRM_TAPPS_LOG("m_DrmCurOffset = %ld", m_DrmCurOffset);
+ DRM_TAPPS_LOG("m_DrmEndOffset = %ld", m_DrmEndOffset);
+
+ DRM_TAPPS_LOG("m_blockCnt = %ld", m_blockCnt);
+ DRM_TAPPS_LOG("m_curBlockIndex = %ld", m_curBlockIndex);
+
+ DrmDecryptBlocks();
+
+ return TADC_SUCCESS;
+
+finish:
+ TADC_MEMFree_FileHeader(&t_FileHeader);
+ TADC_MEMFree_DRMHeader(&t_DRMHeader);
+ TADC_MEMFree_RO(&t_RO);
+
+ return ret;
+}
+
+int DrmFileHandler::DrmSeek(long long offset, int origin)
+{
+ int nRet = TADC_SUCCESS;
+ long long OriginOffset = 0;
+ long long DrmOffset = 0;
+ long long temp = 0;
+
+ m_decReadlen = 0;
+
+ if (origin == SEEK_SET)
+ {
+ DrmOffset = offset;
+ if (DrmOffset < 0 || DrmOffset > m_plaintextSize)
+ {
+ DRM_TAPPS_EXCEPTION("Parameter Wrong! Offset can not be minus. offset=%lld, m_OriginCurOffset=%lld, m_plaintextSize=%lld", offset, m_OriginCurOffset, m_plaintextSize);
+ return TADC_PARAMETER_ERROR;
+ }
+
+ OriginOffset = m_PlaintextStartOffset + DrmOffset;
+ if (fseek(m_pFP, OriginOffset, SEEK_SET) != 0)
+ {
+ DRM_TAPPS_EXCEPTION("fseek failed.");
+ return TADC_FILE_READ_ERROR;
+ }
+
+ m_OriginCurOffset = OriginOffset;
+ m_DrmCurOffset = DrmOffset;
+ }
+ else if (origin == SEEK_CUR)
+ {
+ temp = m_OriginCurOffset;
+
+ if (temp == -1)
+ {
+ DRM_TAPPS_EXCEPTION("GetOriginCurOffset() failed.");
+ return TADC_FILE_READ_ERROR;
+ }
+
+ OriginOffset = temp + offset;
+ DrmOffset = OriginOffset - m_PlaintextStartOffset;
+
+ if (DrmOffset < 0 || DrmOffset > m_plaintextSize)
+ {
+ DRM_TAPPS_EXCEPTION("Parameter Wrong! Offset can not be minus. offset=%lld, m_OriginCurOffset=%lld, OriginOffset=%lld, DrmOffset=%lld, m_plaintextSize=%lld", offset, temp, OriginOffset, DrmOffset, m_plaintextSize);
+ return TADC_PARAMETER_ERROR;
+ }
+
+ if (fseek(m_pFP, OriginOffset, SEEK_SET) != 0)
+ {
+ DRM_TAPPS_EXCEPTION("fseek failed.");
+ return TADC_FILE_READ_ERROR;
+ }
+
+ m_OriginCurOffset = OriginOffset;
+ m_DrmCurOffset = DrmOffset;
+ }
+ else if (origin == SEEK_END)
+ {
+ OriginOffset = m_OriginEndOffset + offset;
+ if (fseek(m_pFP, OriginOffset, SEEK_SET) != 0)
+ {
+ DRM_TAPPS_EXCEPTION("fseek failed.");
+ return TADC_FILE_READ_ERROR;
+ }
+
+ DrmOffset = OriginOffset - m_PlaintextStartOffset;
+ if (DrmOffset < 0 || DrmOffset > m_plaintextSize)
+ {
+ DRM_TAPPS_EXCEPTION("Parameter Wrong! Offset can not be minus. offset=%lld, m_OriginCurOffset=%lld, OriginOffset=%lld, DrmOffset=%lld, m_plaintextSize=%lld", offset, temp, OriginOffset, DrmOffset, m_plaintextSize);
+ return TADC_PARAMETER_ERROR;
+ }
+
+ m_OriginCurOffset = OriginOffset;
+ m_DrmCurOffset = DrmOffset;
+ }
+ else
+ {
+ DRM_TAPPS_EXCEPTION("Parameter Wrong!");
+ return TADC_PARAMETER_ERROR;
+ }
+
+ return nRet;
+}
+
+long long DrmFileHandler::DrmTell(void)
+{
+ return m_DrmCurOffset;
+// return GetDrmCurOffset();
+}
+
+int DrmFileHandler::DrmDecryptBlocks(void)
+{
+
+ bool bRet = true;
+ int ret = TADC_SUCCESS;
+ const char* packagePath = (const char*)m_pFilePath;
+ long long EncBlockCnt = 0;
+ T_FILE_HEADER t_FileHeader;
+ T_DRM_HEADER t_DRMHeader;
+ T_DEVICE_INFO t_DeviceInfo;
+ T_RO t_RO;
+ DrmTdcFileHeader fileHeader;
+
+ ULONG DecLen = 0;
+ ULONG ReadLen = 0;
+ ULONG k = 0, l= 0;
+
+ // 1. Check the file is TADC DRM file.
+ memset(&t_FileHeader, 0x00, sizeof(t_FileHeader));
+ memset(&t_DRMHeader, 0x00, sizeof(T_DRM_HEADER));
+ memset(&t_DeviceInfo, 0x00, sizeof(T_DEVICE_INFO));
+ memset(&t_RO, 0x00, sizeof(T_RO));
+
+ bRet = DrmTdcGetFileHeader(packagePath, &fileHeader);
+ if (bRet == FALSE)
+ {
+ DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error : DrmTdcGetFileHeader()");
+ ret = TADC_GET_FILEHEADER_ERROR;
+
+ goto finish;
+ }
+
+ bRet = DTappsGetCEK(fileHeader.cid, &t_RO);
+ if(bRet == FALSE)
+ {
+ DRM_TAPPS_SECURE_EXCEPTION("DrmDecryptBlocks Error : DTappsGetCEK() packagePath=%s, fileHeader.cid=%s", packagePath, fileHeader.cid);
+ ret = TADC_GET_CEK_ERROR;
+
+ goto finish;
+ }
+ DRM_TAPPS_SECURE_LOG("fileHeader.cid=%s, t_RO.t_Content.CEK=%s", fileHeader.cid, t_RO.t_Content.CEK);
+
+ if ((ret = TADC_SetDeviceInfo(&t_DeviceInfo) ) == TADC_GETDUID_ERROR)
+ {
+ DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error : TADC_SetDeviceInfo(), TADC Error Code - %d", ret);
+ ret = TADC_FILE_READ_ERROR;
+
+ goto finish;
+ }
+
+ ret = TADC_GetDRMHeaderFromFile(packagePath, &t_FileHeader, &t_DRMHeader);
+ if (ret < 0)
+ {
+ DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error : TADC_GetDRMHeaderFromFile() - %s, TADC Error Code - %d", packagePath, ret);
+ ret = TADC_NOTTADCFILE_ERROR;
+
+ goto finish;
+ }
+
+ //Get CEK
+ if ((ret = TADC_GetCEK(&t_DeviceInfo, &t_RO, &t_DRMHeader )) < 0)
+ {
+ DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error: TADC_GetCEK, TADC Error Code - %d", ret);
+ ret = TADC_GET_CEK_ERROR;
+
+ goto finish;
+ }
+
+ if (fseek(m_pFP, m_PlaintextStartOffset, SEEK_SET ) != 0)
+ {
+ DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error :fseek failed.");
+ ret = TADC_FILE_READ_ERROR;
+
+ goto finish;
+ }
+
+ if (m_encryptionRange == -1)
+ {
+ EncBlockCnt = m_blockCnt;
+ }
+ else
+ {
+ EncBlockCnt = m_encryptionRange;
+ }
+
+ m_pDecBuf = new unsigned char[(EncBlockCnt * TDC_DECRYPT_BLOCKSIZE) + 1];
+ if (m_pDecBuf == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("DrmRead Error : m_pDecBuf Memory allocation failed");
+ return TADC_MEMAlOC_ERROR;
+ }
+
+ ReadLen = fread(m_pDecBuf, 1, EncBlockCnt * TDC_DECRYPT_BLOCKSIZE, m_pFP);
+
+ for (k = 0 ; k < ReadLen ; k += 512)
+ {
+ if (l < EncBlockCnt)
+ {
+ DecLen = ReadLen - k;
+ DecLen = ( DecLen > 512) ? 512 : DecLen;
+
+ if ((ret = TADC_DecryptBlock((char*)m_pDecBuf + k, DecLen, &t_DRMHeader)) < 0)
+ {
+ DRM_TAPPS_EXCEPTION("DrmDecryptBlocks Error : TADC_DecryptBlock, TADC Error Code - %d", ret);
+ ret = TADC_DECRYPT_PACKAGE_ERROR;
+ goto finish;
+ }
+ }
+ l += 1;
+ }
+
+finish:
+ TADC_MEMFree_FileHeader(&t_FileHeader);
+ TADC_MEMFree_DRMHeader(&t_DRMHeader);
+ TADC_MEMFree_RO(&t_RO);
+ return ret;
+}
+
+int DrmFileHandler::DrmRead(void* pBuf, long long buflen, long long* pReadLen)
+{
+ unsigned char *pNewReadBuf = NULL;
+ unsigned char *pTempReadBuf = NULL;
+ int ret = TADC_SUCCESS;
+
+ ULONG ReadLen = 0;
+ long long EncBlockCnt = 0;
+
+ if (m_encryptionRange == -1)
+ {
+ EncBlockCnt = m_blockCnt;
+ }
+ else
+ {
+ EncBlockCnt = m_encryptionRange;
+ }
+
+ if (m_DrmCurOffset > EncBlockCnt * TDC_DECRYPT_BLOCKSIZE)
+ {
+ pNewReadBuf = (TADC_U8*)TADC_IF_Malloc(buflen + 1);
+ if (pNewReadBuf == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("DrmRead Error : pNewReadBuf Malloc Fail");
+ return TADC_MEMAlOC_ERROR;
+ }
+
+ ReadLen = fread(pNewReadBuf, 1, buflen, m_pFP);
+
+ TADC_IF_MemCpy(pBuf , pNewReadBuf , ReadLen);
+ TADC_IF_Free(pNewReadBuf);
+
+ *pReadLen = ReadLen;
+ }
+ else
+ {
+ if (buflen > EncBlockCnt * TDC_DECRYPT_BLOCKSIZE - m_DrmCurOffset)
+ {
+ pTempReadBuf = (TADC_U8*)TADC_IF_Malloc((buflen) + 1);
+ if (pTempReadBuf == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("DrmRead Error : pTempReadBuf Malloc Fail");
+ ret = TADC_MEMAlOC_ERROR;
+
+ goto finish;
+ }
+
+ m_decReadlen = (EncBlockCnt * TDC_DECRYPT_BLOCKSIZE) - m_DrmCurOffset;
+ TADC_IF_MemCpy(pTempReadBuf , (char*)m_pDecBuf + m_DrmCurOffset , m_decReadlen);
+
+ m_extraReadlen = buflen - m_decReadlen;
+
+ if (fseek(m_pFP, m_decReadlen, SEEK_CUR) != 0)
+ {
+ DRM_TAPPS_EXCEPTION("DrmRead Error: fseek failed.");
+ ret = TADC_FILE_READ_ERROR;
+
+ goto finish;
+ }
+
+ pNewReadBuf = (TADC_U8*)TADC_IF_Malloc(m_extraReadlen + 1);
+ if (pNewReadBuf == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("DrmRead Error : pNewReadBuf Malloc Fail");
+ ret = TADC_MEMAlOC_ERROR;
+ goto finish;
+ }
+
+ ReadLen = fread(pNewReadBuf, 1, m_extraReadlen, m_pFP);
+
+ TADC_IF_MemCpy((char*)pTempReadBuf + m_decReadlen, pNewReadBuf , ReadLen);
+ TADC_IF_MemCpy(pBuf , pTempReadBuf , buflen);
+
+ TADC_IF_Free(pNewReadBuf);
+ TADC_IF_Free(pTempReadBuf);
+ }
+ else
+ {
+ if (m_DrmCurOffset == 0)
+ {
+ TADC_IF_MemCpy(pBuf, (char*)m_pDecBuf + m_decReadlen , buflen);
+ }
+ else
+ {
+ TADC_IF_MemCpy(pBuf, (char*)m_pDecBuf + m_DrmCurOffset + m_decReadlen, buflen);
+ }
+ m_decReadlen = m_decReadlen + buflen;
+ }
+
+ *pReadLen = buflen;
+ }
+
+ return TADC_SUCCESS;
+
+finish:
+ TADC_IF_Free(pNewReadBuf);
+ TADC_IF_Free(pTempReadBuf);
+ return ret;
+}
+
+long long DrmFileHandler::GetCurBlockIndex(void)
+{
+ m_curBlockIndex = (m_DrmCurOffset / 512) + ((m_DrmCurOffset % 512) ? 1 : 0);
+
+ return m_curBlockIndex;
+}
diff --git a/tadcore/DrmFileHandleMgr/DrmFileMgr.cpp b/tadcore/DrmFileHandleMgr/DrmFileMgr.cpp
new file mode 100644
index 0000000..d1e1ae0
--- /dev/null
+++ b/tadcore/DrmFileHandleMgr/DrmFileMgr.cpp
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 <time.h>
+
+#include <new>
+#include <cstring>
+
+#include "DrmFileMgr.h"
+#include "TADC_ErrorCode.h"
+#include "drm_intf_tapps.h"
+
+DrmFileMgr *DrmFileMgr::m_pInstance = NULL;
+
+DrmFileMgr::DrmFileMgr(void)
+{
+}
+
+DrmFileMgr::~DrmFileMgr(void)
+{
+ for (auto it = m_HandlerMap.begin(); it != m_HandlerMap.end(); ++it)
+ if (it->second != NULL)
+ delete it->second;
+}
+
+DrmFileMgr *DrmFileMgr::GetInstance(void)
+{
+ if (m_pInstance != NULL)
+ return m_pInstance;
+
+ m_pInstance = new (std::nothrow) DrmFileMgr();
+ if (m_pInstance == NULL) {
+ DRM_TAPPS_EXCEPTION("Creating DrmFileMgr m_pInstance failed.");
+ return NULL;
+ }
+
+ m_pInstance->Construct();
+
+ DRM_TAPPS_LOG("m_pInstance is successfully created.");
+
+ return m_pInstance;
+}
+
+void DrmFileMgr::FreeInstance(void)
+{
+ if (m_pInstance != NULL) {
+ delete m_pInstance;
+ m_pInstance = NULL;
+ }
+}
+
+void DrmFileMgr::Construct(void)
+{
+ srand(time(NULL));
+}
+
+int DrmFileMgr::OpenFileHandler(const char *filePath, int mode, int *key)
+{
+ //DRM_TAPPS_LOG("%s) started. key=%d", __func__, *key);
+
+ if (filePath == NULL || strlen(filePath) < 1) {
+ DRM_TAPPS_EXCEPTION("Parameters NULL!");
+ return TADC_PARAMETER_ERROR;
+ }
+
+ auto pDrmFileHandler = new (std::nothrow) DrmFileHandler();
+ if (pDrmFileHandler == NULL) {
+ DRM_TAPPS_EXCEPTION("DrmFileHandler allocation failed.");
+ return TADC_MEMAlOC_ERROR;
+ }
+
+ if (pDrmFileHandler->Construct(filePath) != TADC_SUCCESS) {
+ delete pDrmFileHandler;
+ DRM_TAPPS_EXCEPTION("DrmFileHandler Construct failed.");
+ return TADC_MEMAlOC_ERROR;
+ }
+
+ unsigned int seed = time(NULL);
+ int tmpKey = rand_r(&seed);
+
+ m_HandlerMap.emplace(tmpKey, pDrmFileHandler);
+
+ *key = tmpKey;
+
+ //SECURE_LOGI("FileHandler is successfully created. key=%d, file=%s", *key, filePath);
+
+ return TADC_SUCCESS;
+}
+
+int DrmFileMgr::CloseFileHandler(int key)
+{
+ //DRM_TAPPS_LOG("%s) started. key=%d", __func__, key);
+
+ if (m_HandlerMap.count(key) == 0) {
+ DRM_TAPPS_EXCEPTION("DrmFileHandler is not exist. key=%d", key);
+ return TADC_GET_FILE_HANDLER_ERROR;
+ }
+
+ auto &pHandler = m_HandlerMap[key];
+ if (pHandler != NULL)
+ delete pHandler;
+
+ m_HandlerMap.erase(key);
+
+ //DRM_TAPPS_LOG("%s) FileHandler is successfully closed. key=%d", __func__, key);
+
+ return TADC_SUCCESS;
+}
+
+int DrmFileMgr::GetFileHandler(int key, DrmFileHandler **handler)
+{
+ //DRM_TAPPS_LOG("%s) started. key=%d", __func__, key);
+
+ if (m_HandlerMap.count(key) == 0) {
+ DRM_TAPPS_EXCEPTION("DrmFileHandler is not exist. key=%d", key);
+ return TADC_GET_FILE_HANDLER_ERROR;
+ }
+
+ *handler = m_HandlerMap[key];
+
+ //DRM_TAPPS_LOG("FileHandler is successfully retrived. key=%d, ret=%x", key, ret);
+
+ return TADC_SUCCESS;
+}
diff --git a/tadcore/Svc/DrmTdcSvc.cpp b/tadcore/Svc/DrmTdcSvc.cpp
new file mode 100644
index 0000000..01ab669
--- /dev/null
+++ b/tadcore/Svc/DrmTdcSvc.cpp
@@ -0,0 +1,636 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 DrmTdcSvc.cpp
+ * @brief This file is for TADC Testcase temporarily.
+ * @author Sangil Yoon (si83.yoon@samsung.com)
+ * @version 1.0
+ *
+*/
+
+#include "TADC_Core.h"
+#include "TADC_IF.h"
+
+#include "TADC_ErrorCode.h"
+
+#include "DrmTdcSvc.h"
+
+#define DHINFO_MAX 100
+#define DHINFO_REQIDLEN 20
+
+#define TDC_DECRYPT_IOLEN 1024*1024 // 1024 Kbyte
+
+//DH Session Info Structure
+typedef struct
+{
+ BYTE hashReqID[DHINFO_MAX][DHINFO_REQIDLEN]; //LicenseRequest Request ID Hash 20byte
+ T_ROACQ_INFO t_ROAcqInfo[DHINFO_MAX]; //DH Info
+
+} DrmTdcDHInfo;
+
+
+static DrmTdcDHInfo g_DrmTdcDHInfo;
+static BOOL g_DrmTdcDHFlag = FALSE;
+
+static char g_sTimeStamp[21]; //2011.03.08, GMT ("CCCC-YY-MMThh:mm:ssZ")
+
+bool DrmTdcGetFileHeader
+(
+ IN const char *pTADCFilepath, //TDC DRM File Path
+ IN OUT DrmTdcFileHeader *pFileHeader //File Header Info ( CID, License URL )
+)
+{
+ T_FILE_HEADER t_FileHeader;
+ T_DRM_HEADER t_DRMHeader;
+
+ //null check
+ if (!pTADCFilepath || !pFileHeader) {
+ DRM_TAPPS_EXCEPTION("DrmTdcGetFileHeader Error : Parameter Null");
+ return FALSE;
+ }
+
+ //Init
+ memset(&t_FileHeader, 0x00, sizeof(T_FILE_HEADER));
+ memset(&t_DRMHeader, 0x00, sizeof(T_DRM_HEADER));
+ memset(pFileHeader, 0x00, sizeof(DrmTdcFileHeader));
+
+ //Get DRM Header Info
+ if (TADC_GetDRMHeaderFromFile(pTADCFilepath, &t_FileHeader, &t_DRMHeader) < 0) {
+ DRM_TAPPS_EXCEPTION("DrmTdcGetFileHeader Error : TADC_GetDRMHeaderFromFile (%s)", pTADCFilepath);
+ TADC_MEMFree_DRMHeader(&t_DRMHeader);
+ return FALSE;
+ }
+
+ //Copy to pFileHeader ( CID, RIURL )
+ if( (sizeof(pFileHeader->cid) < strlen((char *)t_DRMHeader.CID) + 1 ) ||
+ (sizeof(pFileHeader->riurl) < strlen((char *)t_DRMHeader.RIURL) + 1 )) {
+ DRM_TAPPS_EXCEPTION("DrmTdcGetFileHeader Error : TADC_GetDRMHeaderFromFile. Invalid cid or riurl(%s)", pTADCFilepath);
+ TADC_MEMFree_FileHeader(&t_FileHeader);
+ TADC_MEMFree_DRMHeader(&t_DRMHeader);
+ return FALSE;
+ }
+ memcpy(pFileHeader->cid, t_DRMHeader.CID, strlen((char *)t_DRMHeader.CID) + 1);
+ memcpy(pFileHeader->riurl, t_DRMHeader.RIURL, strlen((char *)t_DRMHeader.RIURL) + 1);
+
+ //Free
+ TADC_MEMFree_FileHeader(&t_FileHeader);
+ TADC_MEMFree_DRMHeader(&t_DRMHeader);
+
+ return TRUE;
+}
+
+bool DrmTdcDecryptPackage
+(
+ IN const char *pTADCFilepath, //TDC DRM File Path
+ IN const char *pLicenseBuf, //Decrypted Rights Object
+ IN unsigned int licenseBufLen, //pDecLicenseBuf Length
+ IN const char *pDecryptedFile //Decrypted File Path
+)
+{
+ T_FILE_HEADER t_FileHeader;
+ T_DRM_HEADER t_DRMHeader;
+ T_DEVICE_INFO t_DeviceInfo;
+ T_RO t_RO;
+
+
+ long long offset = 0, BlockCnt = 0, EncBlockCnt = 0, size1 = 0, size2 = 0;
+ FILE *hFile1 = INVALID_HOBJ; //TDC drm file
+ FILE *hFile2 = INVALID_HOBJ; //Decrypted file
+
+ //unsigned char tempbuf[512]; // Decrypt Block
+ unsigned char *pReadBuf; // File Read buffer
+
+ ULONG i = 0, k = 0, DecLen = 0;
+
+ //2011.03.08, init
+ memset(&t_FileHeader, 0x00, sizeof(T_FILE_HEADER));
+ memset(&t_DRMHeader, 0x00, sizeof(T_DRM_HEADER));
+ memset(&t_DeviceInfo, 0x00, sizeof(T_DEVICE_INFO));
+ memset(&t_RO, 0x00, sizeof(T_RO));
+
+ //null check
+ if (!pTADCFilepath
+ || !pLicenseBuf
+ || !pDecryptedFile
+ || licenseBufLen < 1) {
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptPackage Error : Parameter Null");
+ return FALSE;
+ }
+
+ //Set DeviceInfo
+ if (TADC_SetDeviceInfo(&t_DeviceInfo) < 0) {
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptPackage Error : TADC_SetDeviceInfo");
+ return FALSE;
+ }
+
+ pReadBuf = (TADC_U8*)TADC_IF_Malloc(TDC_DECRYPT_IOLEN);
+ if (!pReadBuf) {
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptPackage Error : pReadBuf Malloc Fail");
+ return FALSE;
+ }
+
+ //Get DRM Header Info
+ if (TADC_GetDRMHeaderFromFile(pTADCFilepath, &t_FileHeader, &t_DRMHeader) < 0) {
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptPackage Error : TADC_GetDRMHeaderFromFile");
+ TADC_MEMFree_FileHeader(&t_FileHeader);
+ TADC_MEMFree_DRMHeader(&t_DRMHeader);
+ TADC_IF_Free(pReadBuf);
+ return FALSE;
+ }
+
+ // RO XML Parser
+ if (TADC_GetResponseROInfo((unsigned char*)pLicenseBuf, &t_RO) < 0) {
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptPackage Error : TADC_GetResponseROInfo");
+ TADC_MEMFree_FileHeader(&t_FileHeader);
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptPackage Debug : 1");
+
+ TADC_MEMFree_DRMHeader(&t_DRMHeader);
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptPackage Debug : 2");
+
+ TADC_MEMFree_RO(&t_RO);
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptPackage Debug : 3");
+
+ TADC_IF_Free(pReadBuf);
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptPackage Debug : 4");
+
+ return FALSE;
+ }
+
+ //Get CEK
+ if (TADC_GetCEK(&t_DeviceInfo, &t_RO, &t_DRMHeader) < 0) {
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptPackage Error : TADC_GetCEK");
+ TADC_MEMFree_FileHeader(&t_FileHeader);
+ TADC_MEMFree_DRMHeader(&t_DRMHeader);
+ TADC_MEMFree_RO(&t_RO);
+ TADC_IF_Free(pReadBuf);
+ return FALSE;
+ }
+
+ //Decrypt File
+ //File Open ( DRM File )
+ if ((hFile1 = fopen(pTADCFilepath, "rb")) == INVALID_HOBJ) {
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptPackage Error : DRM FmOpenFile (%s)", pTADCFilepath);
+ TADC_MEMFree_FileHeader(&t_FileHeader);
+ TADC_MEMFree_DRMHeader(&t_DRMHeader);
+ TADC_MEMFree_RO(&t_RO);
+ TADC_IF_Free(pReadBuf);
+ return FALSE;
+ }
+
+ //File Create ( Decrypted File )
+ if ((hFile2 = fopen(pDecryptedFile, "w+b")) == INVALID_HOBJ) {
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptPackage Error : Decrypted File FmOpenFile (%s)", pDecryptedFile);
+ fclose(hFile1);
+ TADC_MEMFree_FileHeader(&t_FileHeader);
+ TADC_MEMFree_DRMHeader(&t_DRMHeader);
+ TADC_MEMFree_RO(&t_RO);
+ TADC_IF_Free(pReadBuf);
+ return FALSE;
+ }
+
+ fseek(hFile1, 0, SEEK_END);
+ size1 = ftell(hFile1);
+
+ offset = t_FileHeader.Offset1 + 35 + t_DRMHeader.XmlSize;
+ fseek(hFile1, offset, SEEK_SET );
+
+ size2 = size1 - offset; //plain file size
+ BlockCnt = (size2 / 512) + ( (size2 % 512) ? 1 : 0 );
+
+ if (t_DRMHeader.EncryptionRange == -1)
+ EncBlockCnt = BlockCnt;
+ else
+ EncBlockCnt = t_DRMHeader.EncryptionRange;
+
+ i = 0;
+
+ while (i < BlockCnt) {
+ ULONG ReadLen = fread(pReadBuf, 1, TDC_DECRYPT_IOLEN, hFile1);
+
+ if (ReadLen < 1)
+ break;
+
+ for (k = 0 ; k < ReadLen ; k += 512) {
+ if (i < EncBlockCnt) {
+ DecLen = ReadLen - k;
+ DecLen = (DecLen > 512) ? 512 : DecLen;
+
+ if (TADC_DecryptBlock((char*)pReadBuf + k, DecLen, &t_DRMHeader) < 0 ) {
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptPackage Error : TADC_DecryptBlock");
+ fclose(hFile1);
+ fclose(hFile2);
+ TADC_MEMFree_FileHeader(&t_FileHeader);
+ TADC_MEMFree_DRMHeader(&t_DRMHeader);
+ TADC_MEMFree_RO(&t_RO);
+ TADC_IF_Free(pReadBuf);
+ return FALSE;
+ }
+ }
+ i += 1;
+ }
+ fwrite(pReadBuf, 1, ReadLen, hFile2);
+ }
+
+ fclose(hFile1); //sample drm file
+ fclose(hFile2); //plain file
+
+ TADC_MEMFree_FileHeader(&t_FileHeader);
+ TADC_MEMFree_DRMHeader(&t_DRMHeader);
+ TADC_MEMFree_RO(&t_RO);
+ TADC_IF_Free(pReadBuf);
+
+ return TRUE;
+}
+
+bool DrmTdcDecryptPackage2
+(
+ IN const char *pTADCFilepath, //TDC DRM File Path
+ IN T_RO t_RO, //RO Info
+ IN const char *pDecryptedFile //Decrypted File Path
+)
+{
+ T_FILE_HEADER t_FileHeader;
+ T_DRM_HEADER t_DRMHeader;
+ T_DEVICE_INFO t_DeviceInfo;
+
+
+ long long offset = 0, BlockCnt = 0, EncBlockCnt = 0, size1 = 0, size2 = 0;
+ FILE* hFile1 = INVALID_HOBJ; //TDC drm file
+ FILE* hFile2 = INVALID_HOBJ; //Decrypted file
+
+ unsigned char *pReadBuf; // File Read buffer
+
+ ULONG i = 0, k = 0, DecLen = 0;
+
+ //2011.03.08, init
+ memset(&t_FileHeader, 0x00, sizeof(T_FILE_HEADER));
+ memset(&t_DRMHeader, 0x00, sizeof(T_DRM_HEADER));
+ memset(&t_DeviceInfo, 0x00, sizeof(T_DEVICE_INFO));
+
+ if (!pTADCFilepath || !pDecryptedFile) {
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptPackage2 Error : Parameter Null");
+ return FALSE;
+ }
+
+ //Set DeviceInfo
+ if (TADC_SetDeviceInfo(&t_DeviceInfo) == TADC_GETDUID_ERROR) {
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptPackage2 Error : TADC_SetDeviceInfo");
+ return FALSE;
+ }
+
+ pReadBuf = (TADC_U8*)TADC_IF_Malloc(TDC_DECRYPT_IOLEN);
+ if (!pReadBuf) {
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptPackage2 Error : pReadBuf Malloc Fail");
+ return FALSE;
+ }
+
+ //Get DRM Header Info
+ if (TADC_GetDRMHeaderFromFile(pTADCFilepath, &t_FileHeader, &t_DRMHeader) < 0) {
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptPackage2 Error : TADC_GetDRMHeaderFromFile");
+ TADC_MEMFree_FileHeader(&t_FileHeader);
+ TADC_MEMFree_DRMHeader(&t_DRMHeader);
+ TADC_IF_Free(pReadBuf);
+ return FALSE;
+ }
+
+ //Get CEK
+ if (TADC_GetCEK(&t_DeviceInfo, &t_RO, &t_DRMHeader) < 0) {
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptPackage2 Error : TADC_GetCEK");
+ TADC_MEMFree_FileHeader(&t_FileHeader);
+ TADC_MEMFree_DRMHeader(&t_DRMHeader);
+ TADC_IF_Free(pReadBuf);
+ return FALSE;
+ }
+
+ //Decrypt File
+ //File Open ( DRM File )
+ if ((hFile1 = fopen(pTADCFilepath, "rb")) == INVALID_HOBJ) {
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptPackage2 Error : DRM FmOpenFile (%s)", pTADCFilepath);
+ TADC_MEMFree_FileHeader(&t_FileHeader);
+ TADC_MEMFree_DRMHeader(&t_DRMHeader);
+ TADC_IF_Free(pReadBuf);
+ return FALSE;
+ }
+
+ //File Create ( Decrypted File )
+ if ((hFile2 = fopen(pDecryptedFile, "w+b")) == INVALID_HOBJ) {
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptPackage2 Error : Decrypted File FmOpenFile (%s)", pDecryptedFile);
+ fclose(hFile1);
+ TADC_MEMFree_FileHeader(&t_FileHeader);
+ TADC_MEMFree_DRMHeader(&t_DRMHeader);
+ TADC_IF_Free(pReadBuf);
+ return FALSE;
+ }
+
+ fseek(hFile1, 0, SEEK_END);
+ size1 = ftell(hFile1);
+
+ offset = t_FileHeader.Offset1 + 35 + t_DRMHeader.XmlSize;
+ fseek(hFile1, offset, SEEK_SET );
+
+ size2 = size1 - offset; //plain file size
+ BlockCnt = (size2 / 512) + ((size2 % 512) ? 1 : 0);
+
+ if (t_DRMHeader.EncryptionRange == -1)
+ EncBlockCnt = BlockCnt;
+ else
+ EncBlockCnt = t_DRMHeader.EncryptionRange;
+
+ i = 0;
+
+ while (i < BlockCnt) {
+ ULONG ReadLen = fread(pReadBuf, 1, TDC_DECRYPT_IOLEN, hFile1);
+
+ if (ReadLen < 1)
+ break;
+
+ for (k = 0 ; k < ReadLen ; k += 512) {
+ if (i < EncBlockCnt) {
+ DecLen = ReadLen - k;
+ DecLen = ( DecLen > 512) ? 512 : DecLen;
+
+ if (TADC_DecryptBlock((char*)pReadBuf + k, DecLen, &t_DRMHeader) < 0) {
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptPackage2 Error : TADC_DecryptBlock");
+ fclose(hFile1);
+ fclose(hFile2);
+ TADC_MEMFree_FileHeader(&t_FileHeader);
+ TADC_MEMFree_DRMHeader(&t_DRMHeader);
+ TADC_IF_Free(pReadBuf);
+ return FALSE;
+ }
+ }
+ i += 1;
+ }
+ fwrite(pReadBuf, 1, ReadLen, hFile2);
+ }
+
+ fclose(hFile1); //sample drm file
+ fclose(hFile2); //plain file
+
+ TADC_MEMFree_FileHeader(&t_FileHeader);
+ TADC_MEMFree_DRMHeader(&t_DRMHeader);
+ TADC_IF_Free(pReadBuf);
+
+ return TRUE;
+}
+
+bool DrmTdcGeneratePurchaseRequest
+(
+ IN const char *pTADCFilepath, //TDC DRM File Path
+ IN OUT char *pReqBuf, //Purchase Request Data
+ IN OUT unsigned int *pReqBufLen, //IN : pReqBuf Length, OUT : Purchase Request Data String Size ( including null terminator )
+ IN OUT char *pLicenseUrl, //License Acquisition URL Data
+ IN OUT unsigned int *pLicenseUrlLen //IN : pLicenseUrl Length, OUT : License Server URL Data String Size ( including null terminator )
+)
+{
+ T_FILE_HEADER t_FileHeader;
+ T_DRM_HEADER t_DRMHeader;
+ T_DEVICE_INFO t_DeviceInfo;
+ char ReqLicBuf[REQU_MAXSIZE] = {0}; //Request buff max size. (2011.03.08)
+
+ //null check
+ if (!pTADCFilepath
+ || !pReqBuf
+ || !pLicenseUrl
+ || *pReqBufLen < 512
+ || *pLicenseUrlLen < 512) {
+ DRM_TAPPS_EXCEPTION("DrmTdcGeneratePurchaseRequest Error : Parameter Null");
+ return FALSE;
+ }
+
+ memset(&t_FileHeader, 0x00, sizeof(T_FILE_HEADER));
+ memset(&t_DRMHeader, 0x00, sizeof(T_DRM_HEADER));
+ memset(&t_DeviceInfo, 0x00, sizeof(T_DEVICE_INFO));
+
+ //Set DeviceInfo
+ if (TADC_SetDeviceInfo(&t_DeviceInfo) == TADC_GETDUID_ERROR) {
+ DRM_TAPPS_EXCEPTION("DrmTdcGeneratePurchaseRequest Error : TADC_SetDeviceInfo");
+ return FALSE;
+ }
+
+ //Get DRM Header Info
+ if (TADC_GetDRMHeaderFromFile(pTADCFilepath, &t_FileHeader, &t_DRMHeader) < 0) {
+ DRM_TAPPS_EXCEPTION("DrmTdcGeneratePurchaseRequest Error : TADC_GetDRMHeaderFromFile");
+ TADC_MEMFree_DRMHeader(&t_DRMHeader);
+ return FALSE;
+ }
+
+ if (TADC_MakeRequestLicense(&t_DeviceInfo, &t_FileHeader, &t_DRMHeader, (unsigned char*)ReqLicBuf, sizeof(ReqLicBuf)) < 0) {
+ DRM_TAPPS_EXCEPTION("DrmTdcGeneratePurchaseRequest Error : TADC_MakeRequestLicense");
+ TADC_MEMFree_DRMHeader(&t_DRMHeader);
+ return FALSE;
+ }
+
+ //Copy pReqBuf
+ size_t tmpLen = strlen((char *)ReqLicBuf);
+ if (*pReqBufLen <= tmpLen) {
+ DRM_TAPPS_EXCEPTION("DrmTdcGeneratePurchaseRequest Error : *pReqBufLen(%d) <= %d", *pReqBufLen, tmpLen);
+ TADC_MEMFree_DRMHeader(&t_DRMHeader);
+ return FALSE;
+ }
+
+ memcpy(pReqBuf, ReqLicBuf, tmpLen + 1);
+
+ //Copy License URL
+ tmpLen = strlen((char *)t_DRMHeader.RIURL);
+ if (*pLicenseUrlLen <= tmpLen) {
+ DRM_TAPPS_EXCEPTION("DrmTdcGeneratePurchaseRequest Error : *pLicenseUrlLen(%d) <= %d", *pLicenseUrlLen, tmpLen);
+ TADC_MEMFree_DRMHeader(&t_DRMHeader);
+ return FALSE;
+ }
+
+ memcpy(pLicenseUrl, t_DRMHeader.RIURL, tmpLen + 1);
+
+ //Free
+ TADC_MEMFree_FileHeader(&t_FileHeader);
+ TADC_MEMFree_DRMHeader(&t_DRMHeader);
+
+ return TRUE;
+}
+
+int DrmTdcGenerateLicenseRequest
+(
+ IN const char *pRespBuf, //Response Data String of the Purchase Request ( Null terminator string )
+ IN unsigned int respBufLen, //pResBuf Length
+ IN OUT char *pReqBuf, //License Request Data
+ IN OUT unsigned int *pReqBufLen, //IN : pReqBuf Length, OUT : Rights Request Data String Size ( including null terminator )
+ IN OUT char *pLicenseUrl, //License Acquisition URL Data
+ IN OUT unsigned int *pLicenseUrlLen //IN : pLicenseUrl Length, OUT : Rights Issuer Server URL Data String Size ( including null terminator )
+)
+{
+ T_ROACQ_INFO *pt_ROAcqInfo = NULL;
+
+ char ReqROBuf[REQU_MAXSIZE] = {0}; //Request buff max size. (2011.03.08)
+ BYTE sha1_tmp[DHINFO_REQIDLEN] = {0};
+ int idx = 0;
+ unsigned char ROVer[2]; //2011.03.08
+
+ //null check
+ if (!pRespBuf
+ || !pReqBuf
+ || !pLicenseUrl
+ || respBufLen < 1
+ || *pReqBufLen < 512
+ || *pLicenseUrlLen < 512) {
+ DRM_TAPPS_EXCEPTION("DrmTdcGenerateLicenseRequest Error : Parameter Null");
+ return TADC_PARAMETER_ERROR;
+ }
+
+ if (g_DrmTdcDHFlag == FALSE) {
+ DrmTdcDHInfoInit();
+ g_DrmTdcDHFlag = TRUE;
+ }
+
+ for (idx = 0 ; idx < DHINFO_MAX ; idx++) {
+ if (!TADC_IF_MemCmp(g_DrmTdcDHInfo.hashReqID[idx], sha1_tmp, DHINFO_REQIDLEN)) {
+ pt_ROAcqInfo = &g_DrmTdcDHInfo.t_ROAcqInfo[idx];
+ break;
+ }
+ }
+
+ // Debug
+ DRM_TAPPS_LOG("DrmTdcGenerateLicenseRequest ID Idx = %d", idx);
+
+ if (idx == DHINFO_MAX) {
+ DRM_TAPPS_EXCEPTION("DrmTdcGenerateLicenseRequest Error : idx == DHINFO_MAX");
+ return TADC_DHINFO_MAX_ERROR;
+ }
+
+ //Get ReqID
+ if (TADC_GetROAcqInfo((unsigned char*)pRespBuf, pt_ROAcqInfo) < 0) {
+ DRM_TAPPS_EXCEPTION("DrmTdcGenerateLicenseRequest Error : TADC_GetROAcqInfo");
+ return TADC_GET_ROACQ_INFO_ERROR;
+ }
+
+ ROVer[0] = 2;
+ ROVer[1] = 0;
+
+ if (TADC_MakeRequestRO(pt_ROAcqInfo, (unsigned char*)ReqROBuf, sizeof(ReqROBuf), ROVer) < 0) {
+ DRM_TAPPS_EXCEPTION("DrmTdcGenerateLicenseRequest Error : TADC_MakeRequestRO");
+ return TADC_MAKE_LICENSEREQ_ERROR;
+ }
+
+ // Debug
+ DRM_TAPPS_LOG("Debug Log == Copy ReqID Hash Successfully Done!");
+
+ //Copy ReqID Hash
+ TADC_IF_SHA1(pt_ROAcqInfo -> ReqID, TADC_IF_StrLen((char*)pt_ROAcqInfo -> ReqID), g_DrmTdcDHInfo.hashReqID[idx]);
+
+ //Copy pReqBuf
+ size_t tmpLen = strlen((char *)ReqROBuf);
+ if (*pReqBufLen <= tmpLen) {
+ DRM_TAPPS_EXCEPTION("DrmTdcGenerateLicenseRequest Error : *pReqBufLen(%d) <= %d", *pReqBufLen, tmpLen);
+ return TADC_MEMAlOC_ERROR;
+ }
+
+ memcpy(pReqBuf, ReqROBuf, tmpLen + 1);
+
+ //Copy License URL
+ tmpLen = strlen((char *)pt_ROAcqInfo->ROAcqURL);
+ if (*pLicenseUrlLen <= tmpLen) {
+ DRM_TAPPS_EXCEPTION("DrmTdcGenerateLicenseRequest Error : *pLicenseUrlLen(%d) <= %d", *pLicenseUrlLen, tmpLen);
+ return TADC_MEMAlOC_ERROR;
+ }
+
+ memcpy(pLicenseUrl, (char *)pt_ROAcqInfo->ROAcqURL, tmpLen + 1);
+
+ // Debug
+ DRM_TAPPS_LOG("Debug Log == DrmTdcGenerateLicenseRequest Successfully Done!");
+
+ return TADC_SUCCESS;
+}
+
+int DrmTdcDecryptLicense
+(
+ IN const char *pRespBuf, //Response Data String of the Rights Request ( Null terminator string )
+ IN unsigned int respBufLen, //pResBuf Length
+ IN OUT char *pDecLicenseBuf, //Decrypted Rights Object
+ IN OUT unsigned int *decLicenseBufLen //IN : pDecLicenseBuf Length, OUT : Decrypted Rights Object String Size ( including null terminator )
+)
+{
+ T_ROACQ_INFO *pt_ROAcqInfo=NULL;
+ T_RO t_RO;
+ int ret = 0;
+ int idx = 0;
+ BYTE sha1_tmp[20] = {0};
+
+ //null check
+ if (!pRespBuf
+ || !pDecLicenseBuf
+ || respBufLen < 1
+ || *decLicenseBufLen < 512) {
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptLicense Error : Parameter Null \n");
+ return TADC_PARAMETER_ERROR;
+ }
+
+ memset(&t_RO, 0x00, sizeof(T_RO));
+
+ if (TADC_GetHashReqID((unsigned char*)pRespBuf, sha1_tmp) < 0) {
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptLicense Error : TADC_GetHashReqID \n");
+ return TADC_GET_HASHREQID_ERROR;
+ }
+
+ for (idx = 0; idx < DHINFO_MAX; idx++) {
+ if (!TADC_IF_MemCmp(g_DrmTdcDHInfo.hashReqID[idx], sha1_tmp, 20)) {
+ pt_ROAcqInfo = &g_DrmTdcDHInfo.t_ROAcqInfo[idx];
+ break;
+ }
+ }
+
+ if (idx == DHINFO_MAX) {
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptLicense Error : idx == DHINFO_MAX!, Session-key is not same.\n");
+ return TADC_DHINFO_MAX_ERROR;
+ }
+
+ //Get Decrypted License
+ if ((ret = TADC_GetResponseRO((unsigned char*)pRespBuf, pt_ROAcqInfo, &t_RO, (unsigned char*)pDecLicenseBuf)) < 0) {
+ DrmTdcDHInfoFree(idx); //2010.02.26
+ DRM_TAPPS_EXCEPTION("DrmTdcDecryptLicense Error : TADC_GetResponseRO! Ret[%x]", ret);
+ return TADC_GET_RORES_INFO_ERROR;
+ }
+ *decLicenseBufLen = strlen(pDecLicenseBuf) + 1;
+
+ // Check Signature and Certificate Chain
+ if ((ret = TADC_VerifyROSignature((unsigned char*)pDecLicenseBuf))) {
+ DRM_TAPPS_EXCEPTION("TADC_VerifyROSignature Error Code = %x", ret);
+ return TADC_RO_SIGNATURE_ERROR;
+ }
+
+ //2011.03.08, return time stamp
+ memcpy(g_sTimeStamp, pt_ROAcqInfo->sTimeStamp, strlen((char *)pt_ROAcqInfo->sTimeStamp) + 1);
+
+ //Free
+ TADC_MEMFree_RO(&t_RO);
+ DrmTdcDHInfoFree(idx);
+
+ return TADC_SUCCESS;
+}
+
+void DrmTdcDHInfoInit(void)
+{
+ memset(&g_DrmTdcDHInfo, 0x00, sizeof(DrmTdcDHInfo));
+}
+
+bool DrmTdcDHInfoFree(int idx)
+{
+ memset(&g_DrmTdcDHInfo.hashReqID[idx], 0x00, sizeof(g_DrmTdcDHInfo.hashReqID[idx]));
+
+ if (TADC_MEMFree_ROAcqInfo(&g_DrmTdcDHInfo.t_ROAcqInfo[idx]) < 0)
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/tadcore/TADCCore/TADC_Core.cpp b/tadcore/TADCCore/TADC_Core.cpp
new file mode 100644
index 0000000..a28c4fc
--- /dev/null
+++ b/tadcore/TADCCore/TADC_Core.cpp
@@ -0,0 +1,1741 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 TADC_Core.cpp
+ * @brief This file includes implementations of the Tizen Apps DRM Core APIs.
+*/
+
+#include "drm-tizen-error.h"
+#include "TADC_Util.h"
+#include "TADC_Sub.h"
+#include "TADC_IF.h"
+#include "TADC_ErrorCode.h"
+
+static BYTE g_baSignatureKey[ 32 ] =
+{
+ 0x29, 0x2b, 0xf2, 0x29, 0x1f, 0x8b, 0x47, 0x81, 0x95, 0xa, 0x84, 0xf8, 0x91, 0xda, 0x7, 0xd0,
+ 0x9c, 0xde, 0x32, 0x3e, 0x9e, 0x46, 0x4a, 0xfc, 0xa4, 0xcc, 0x55, 0x6e, 0xf2, 0x81, 0x61, 0xdb
+};
+
+static BYTE g_baAESKey[ 32 ] =
+{
+ -8, -121, 10, -59, -45, 109, 68, 73, 3, -97, -67, 30, -88, 47, -10,
+ -61, -33, 59, 2, 19, 88, 27, 18, 48, 28, -41, -83, -91, 31, 93, 1, 51
+};
+
+//Error Code
+static DWORD g_TADCErrorCode = 0;
+
+int TADC_SetDeviceInfo(T_DEVICE_INFO *t_DeviceInfo)
+{
+ int nResult = 0;
+
+ TADC_IF_MemSet(t_DeviceInfo, 0, sizeof(T_DEVICE_INFO));
+
+// Mandatory value
+ nResult = TADC_IF_GetDUID((CHAR*)t_DeviceInfo->DUID);
+ IF_ERROR_RETURN(nResult, TADC_GETDUID_ERROR);
+
+ return nResult;
+}
+
+int TADC_MakeRequestLicense( T_DEVICE_INFO *t_DeviceInfo,
+ T_FILE_HEADER *t_FileHeader,
+ T_DRM_HEADER *t_DRMHeader,
+ unsigned char * outBuffer,
+ size_t outBufferSize)
+{
+ int nResult = 0;
+ size_t length = 0;
+
+ //Param Check
+ IF_TRUE_RETURN(outBuffer == NULL, TADC_PARAMETER_ERROR);
+
+ snprintf(
+ (char*)outBuffer,
+ outBufferSize,
+ "<?xml version='1.0'?>\n<request>\n<DeviceInfo>\n<duid>%s</duid>\n</DeviceInfo>\n",
+ t_DeviceInfo->DUID);
+ length = TADC_IF_StrLen((char*)outBuffer);
+ IF_TRUE_RETURN(length <= 0, TADC_XMLPARSER_ERROR);
+
+ //Null Check
+ IF_TRUE_RETURN(t_DRMHeader->SID == NULL, TADC_SID_NULL_ERROR);
+ IF_TRUE_RETURN(t_DRMHeader->CID == NULL, TADC_CID_NULL_ERROR);
+
+ snprintf(
+ (char*)outBuffer + length,
+ outBufferSize - length,
+ "<ContentInfo>\n<DRMType>%d</DRMType>\n<sid>%s</sid>\n<cid>%s</cid>\n</ContentInfo>\n</request>",
+ t_FileHeader->DRMType,
+ t_DRMHeader->SID,
+ t_DRMHeader->CID);
+ length = TADC_IF_StrLen((char*)outBuffer);
+ IF_TRUE_RETURN(length <= 0, TADC_XMLPARSER_ERROR);
+
+ DRM_TAPPS_LOG("TADC_MakeRequestLicense Success!\n");
+
+ return nResult;
+}
+
+int TADC_GetROAcqInfo(unsigned char * inBuffer, T_ROACQ_INFO *t_ROAcqInfo)
+{
+ int nResult = -1;
+ int i = 0, j = 0;
+ int nSize = 0;
+ int length = 0;
+
+ //Check Param buffer
+ IF_TRUE_RETURN(inBuffer == NULL, TADC_PARAMETER_ERROR);
+ nSize = TADC_IF_StrLen((char*) inBuffer);
+ IF_TRUE_RETURN( nSize<=40 || nSize>RESP_MAXSIZE, TADC_PARAMETER_ERROR);
+
+ //Check XML Result Code ( Success result='0' )
+ nResult = -1;
+ for (i = 0 ; i < nSize ; i++)
+ {
+ if (!TADC_IF_MemCmp((char*)(inBuffer+i), "<response result=", 17))
+ {
+ i += 17;
+ if ((!memcmp((char*)(inBuffer+i), "'0'", 3)) || (!memcmp((char*)(inBuffer+i), "\"0\"", 3)))
+ {
+ nResult = 0;
+ break;
+ }
+ else
+ {
+ nResult = -1;
+ }
+ }
+ }
+ IF_TRUE_RETURN(((i == nSize) || (nResult < 0)), TADC_RESPONSEMESSAGE_ERROR);
+
+
+ //Init
+ TADC_IF_MemSet(t_ROAcqInfo, 0, sizeof(T_ROACQ_INFO));
+
+ //Get RIURL
+ length = 0;
+
+ for (i = 0 ; i < nSize ; i++)
+ {
+ if (!TADC_IF_MemCmp((char*)(inBuffer + i), "<riurl>", 7))
+ {
+ i += 7;
+ for (j = i ; j < nSize ; j++)
+ {
+ if (!TADC_IF_MemCmp((char*)(inBuffer + j), "</riurl>", 8))
+ {
+ length = j - i;
+ IF_TRUE_RETURN(length <= 0, TADC_PARAMETER_ERROR);
+ t_ROAcqInfo->ROAcqURL = (TADC_U8*)TADC_IF_Malloc(length + 1);
+ IF_TRUE_RETURN(t_ROAcqInfo->ROAcqURL == NULL, TADC_MEMAlOC_ERROR);
+ TADC_IF_MemSet(t_ROAcqInfo->ROAcqURL, 0, length + 1);
+ TADC_IF_MemCpy(t_ROAcqInfo->ROAcqURL, inBuffer + i, length);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ IF_TRUE_RETURN(length <= 0, TADC_RESPONSEMESSAGE_ERROR);
+
+ //Get ReqID
+ length = 0;
+
+ for (i = 0 ; i < nSize ; i++)
+ {
+ if (!TADC_IF_MemCmp((char*)(inBuffer + i), "<reqid>", 7))
+ {
+ i += 7;
+ for (j = i ; j < nSize ; j++)
+ {
+ if (!TADC_IF_MemCmp((char*)(inBuffer + j), "</reqid>", 8))
+ {
+ length = j - i;
+ IF_TRUE_RETURN(length <= 0, TADC_PARAMETER_ERROR);
+ t_ROAcqInfo->ReqID = (TADC_U8*)TADC_IF_Malloc(length + 1);
+ IF_TRUE_RETURN(t_ROAcqInfo->ReqID == NULL, TADC_MEMAlOC_ERROR);
+ TADC_IF_MemSet(t_ROAcqInfo->ReqID, 0, length + 1);
+ TADC_IF_MemCpy(t_ROAcqInfo->ReqID, inBuffer+i, length);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ IF_TRUE_RETURN(length <= 0, TADC_RESPONSEMESSAGE_ERROR);
+ DRM_TAPPS_LOG("TADC_GetROAcqInfo Success!\n");
+
+ return nResult;
+}
+
+int TADC_MakeRequestRO(T_ROACQ_INFO *t_ROAcqInfo, unsigned char * outBuffer, size_t outBufferSize, unsigned char * ROVer)
+{
+ BYTE sha1_tmp[20];
+ TADC_U8 *ReqTemp;
+ LPSTR psz64Parameter = NULL;
+
+ TADC_U8 key[16];
+ TADC_U8 iv[16];
+
+ int outlen = 0;
+ int nResult = 0;
+
+ size_t StrSize = 0;
+ size_t len = 0;
+ size_t i = 0;
+ size_t k = 0;
+ size_t reqdataset_size = 0;
+
+ // Debug
+ DRM_TAPPS_LOG("Debug Log == TADC_MakeRequestRO : Start \n");
+
+ //Check Param Buffer
+ IF_TRUE_RETURN(outBuffer == NULL, TADC_PARAMETER_ERROR);
+ IF_TRUE_RETURN(t_ROAcqInfo->ReqID == NULL, TADC_PARAMETER_ERROR);
+
+ // Debug
+ DRM_TAPPS_LOG("Debug Log == TADC_MakeRequestRO : After Check Param Buffer \n");
+ len = TADC_IF_StrLen((char*)t_ROAcqInfo->ReqID);
+ IF_TRUE_RETURN( (len <= 0 || len > 512), TADC_PARAMETER_ERROR);
+
+ // Debug
+ DRM_TAPPS_LOG("Debug Log == TADC_MakeRequestRO : After Check t_ROAcqInfo->ReqID Len \n");
+ nResult = TADC_IF_GetDHKey(&t_ROAcqInfo->t_DHInfo);
+ IF_ERROR_RETURN(nResult, TADC_GETDHKEY_ERROR);
+
+ // Debug
+ DRM_TAPPS_LOG("Debug Log == TADC_MakeRequestRO : After TADC_IF_GetDHKey \n");
+ IF_TRUE_RETURN(t_ROAcqInfo->t_DHInfo.pSize <= 0 || t_ROAcqInfo->t_DHInfo.pSize > DHKey_SIZE, TADC_PARAMETER_ERROR);
+ IF_TRUE_RETURN(t_ROAcqInfo->t_DHInfo.ASize <= 0 || t_ROAcqInfo->t_DHInfo.ASize > DHKey_SIZE, TADC_PARAMETER_ERROR);
+
+ //If ROVer 2.0 then add <reqversion> element. 2011.03.08
+ if (ROVer != NULL && ROVer[0] >= 2)
+ {
+ snprintf(
+ (char*)outBuffer,
+ outBufferSize,
+ "<?xml version='1.0'?>\n<request>\n<reqversion>%d.%d</reqversion>\n<reqid>%s</reqid>\n<reqdataset>",
+ ROVer[0],
+ ROVer[1],
+ t_ROAcqInfo->ReqID);
+ }
+ else
+ {
+ snprintf(
+ (char*)outBuffer,
+ outBufferSize,
+ "<?xml version='1.0'?>\n<request>\n<reqid>%s</reqid>\n<reqdataset>",
+ t_ROAcqInfo->ReqID);
+ }
+
+ len = TADC_IF_StrLen((char*)outBuffer);
+ i += len;
+
+ reqdataset_size = i;
+
+ TADC_IF_StrNCpy((char*)outBuffer+i, "p=", 2);
+ i += 2;
+
+ for (k = 0 ; k < t_ROAcqInfo->t_DHInfo.pSize ; k++)
+ {
+ snprintf(
+ (char*)outBuffer + i + (k * 2),
+ outBufferSize - i - (k * 2),
+ "%02X",
+ t_ROAcqInfo->t_DHInfo.p[k]);
+ }
+ i += (k * 2);
+
+ snprintf(
+ (char*)outBuffer + i,
+ outBufferSize - i,
+ ";g=%ld",
+ t_ROAcqInfo->t_DHInfo.g);
+ i += 4;
+
+ TADC_IF_StrNCpy((char*)outBuffer + i, ";A=", 3);
+ i += 3;
+
+ for (k = 0 ; k < t_ROAcqInfo->t_DHInfo.ASize ; k++)
+ {
+ snprintf(
+ (char*)outBuffer + i + (k * 2),
+ outBufferSize - i - (k * 2),
+ "%02X",
+ t_ROAcqInfo->t_DHInfo.A[k]);
+ }
+ i += (k * 2);
+
+ outBuffer[i] = 0;
+
+ StrSize = i - reqdataset_size;
+
+ //MemAlloc
+ ReqTemp = (TADC_U8*)TADC_IF_Malloc(StrSize);
+ IF_TRUE_RETURN(ReqTemp == NULL, TADC_MEMAlOC_ERROR);
+
+ TADC_IF_MemSet(ReqTemp, 0, StrSize);
+ TADC_IF_MemCpy(ReqTemp, outBuffer+reqdataset_size, StrSize);
+ TADC_IF_SHA1(ReqTemp, StrSize, sha1_tmp);
+
+ TADC_IF_MemCpy(key, &g_baAESKey[0], 16);
+ TADC_IF_MemCpy(iv, &g_baAESKey[16], 16);
+ TADC_IF_AES_CTR(16, key, 16, iv, 20, (unsigned char*)sha1_tmp, &outlen, (unsigned char*)sha1_tmp);
+
+ // Debug
+ DRM_TAPPS_LOG("Debug Log == TADC_MakeRequestRO : After TADC_IF_AES_CTR \n");
+
+ psz64Parameter = Base64Encode(sha1_tmp, sizeof(sha1_tmp)); //MemAlloc
+ if (psz64Parameter == NULL)
+ {
+ TADC_IF_Free(ReqTemp);
+ return TADC_MEMAlOC_ERROR;
+ }
+
+ // Debug
+ DRM_TAPPS_LOG("Debug Log == TADC_MakeRequestRO : After Base64Encode \n");
+
+ TADC_IF_StrNCpy((char*)(outBuffer + i), ";hmac=", 6);
+ len = TADC_IF_StrLen((char*)psz64Parameter);
+ TADC_IF_MemCpy(outBuffer + i + 6, psz64Parameter, len);
+ TADC_IF_StrNCpy((char*)outBuffer + i + 6 + len, "</reqdataset>\n</request>", 24);
+
+ //MemFree
+ if (ReqTemp != NULL)
+ {
+ TADC_IF_Free(ReqTemp);
+ ReqTemp = NULL;
+ }
+ if (psz64Parameter != NULL)
+ {
+ TADC_IF_Free(psz64Parameter);
+ psz64Parameter = NULL;
+ }
+
+ len = TADC_IF_StrLen((char*)outBuffer);
+ IF_TRUE_RETURN(len <= 0, TADC_REQMAKEHMAC_ERROR);
+
+ DRM_TAPPS_LOG("TADC_MakeRequestRO Success!\n");
+
+ return len;
+}
+
+int TADC_GetHashReqID(unsigned char * inBuffer, unsigned char *hashReqID)
+{
+ int i = 0, j = 0, nSize = 0;
+ char tmpbuf[512];
+ int length = 0;
+ int nResult = 0;
+
+ //Check Param Buffer
+ IF_TRUE_RETURN(inBuffer == NULL, TADC_PARAMETER_ERROR);
+ IF_TRUE_RETURN(hashReqID == NULL, TADC_PARAMETER_ERROR);
+ nSize = TADC_IF_StrLen((char*)inBuffer);
+ IF_TRUE_RETURN(nSize <= 40 || nSize>RESP_MAXSIZE, TADC_PARAMETER_ERROR);
+
+ //Check XML Result Code ( Success result='0' )
+ nResult = -1;
+
+ for (i = 0 ; i < nSize ; i++)
+ {
+ if (!TADC_IF_MemCmp((char*)(inBuffer + i), "<response result=", 17))
+ {
+ i += 17;
+ if ((!memcmp((char*)(inBuffer + i), "'0'", 3)) || (!memcmp((char*)(inBuffer + i), "\"0\"", 3)))
+ {
+ nResult = 0;
+ break;
+ }
+ else
+ {
+ nResult = -1;
+ }
+ }
+ }
+ IF_TRUE_RETURN(((i == nSize) || (nResult < 0)), TADC_RESPONSEMESSAGE_ERROR);
+
+ //Init
+ TADC_IF_MemSet(tmpbuf, 0, sizeof(tmpbuf));
+
+ //Get reqid
+ length = 0;
+
+ for (i = 0 ; i < nSize ; i++)
+ {
+ if (!TADC_IF_MemCmp(inBuffer + i, "reqid=", 6))
+ {
+ i += 6;
+ for (j = i ; j < nSize ; j++)
+ {
+ if (!TADC_IF_MemCmp(inBuffer + j, ";", 1))
+ {
+ length = j - i;
+ TADC_IF_StrNCpy((char*)tmpbuf, (char*)(inBuffer + i), length);
+ tmpbuf[length] = 0;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ IF_TRUE_RETURN(length <= 0, TADC_RESPONSEMESSAGE_ERROR);
+
+ if ((length = TADC_IF_StrLen(tmpbuf)) != 40)
+ {
+ return -1;
+ }
+
+ if ((nResult = HEX2BIN((char*)tmpbuf, hashReqID, &length)) < 0)
+ {
+ return -1;
+ }
+
+ if (length != 20)
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+int TADC_GetResponseRO(unsigned char * inBuffer, T_ROACQ_INFO *t_ROAcqInfo, T_RO *t_RO, unsigned char *outBuffer)
+{
+ int nHMacSize = 28; // Base64 Enc length of SHA1 20byte
+ TADC_U8 sha1_tmp[20] = {0, };
+ char hmacBuf[512] = {0, };
+ BYTE *ReqTemp = NULL;
+ LPBYTE pbBuffer = NULL;
+
+ TADC_U8 key[16] = {0, };
+ TADC_U8 iv[16] = {0, };
+
+ int outlen = 0;
+
+ char *License = NULL;
+ TCHAR tmpDH_B[DHKey_SIZE * 2 + 1] = {0, };
+
+ // RO XML Parser
+ CXMLFile XMLParser;
+ CPointerArray paChilds;
+
+ //2011.03.08
+ char *timeStamp = NULL;
+ int retLen = 0;
+ int i = 0, j = 0;
+ int nSize = 0;
+ int length = 0;
+ int req_length = 0;
+ int nResult = 0;
+
+ char pRoHeader[36] = {'<', '?', 'x', 'm', 'l', ' ', 'v', 'e', 'r', 's', 'i', 'o', 'n', '=', '"', '1', '.', '0', '"', '?', '>', 0x0A,
+ '<', 'T', 'i', 'z', 'e', 'n', 'L', 'i', 'c', 'e', 'n', 's', 'e', '>'};
+
+ // test code
+ FILE *fd = NULL;
+ char tmpPath[128] = {0, };
+
+ //Check Param Buffer
+ IF_TRUE_RETURN(inBuffer == NULL, TADC_PARAMETER_ERROR);
+ IF_TRUE_RETURN(t_ROAcqInfo== NULL, TADC_PARAMETER_ERROR);
+ IF_TRUE_RETURN(t_RO == NULL, TADC_PARAMETER_ERROR);
+
+ nSize = TADC_IF_StrLen((char*)inBuffer);
+ IF_TRUE_RETURN( nSize <= 40 || nSize>RESP_MAXSIZE, TADC_PARAMETER_ERROR);
+
+ IF_TRUE_RETURN(t_ROAcqInfo->t_DHInfo.pSize<=0 || t_ROAcqInfo->t_DHInfo.pSize>DHKey_SIZE, TADC_PARAMETER_ERROR);
+ IF_TRUE_RETURN(t_ROAcqInfo->t_DHInfo.ASize<=0 || t_ROAcqInfo->t_DHInfo.ASize>DHKey_SIZE, TADC_PARAMETER_ERROR);
+
+ //Check XML Result Code ( Success result='0' )
+ nResult = -1;
+ for (i = 0 ; i < nSize ; i++)
+ {
+ if (!TADC_IF_MemCmp((char*)(inBuffer + i), "<response result=", 17))
+ {
+ i += 17;
+ if ((!memcmp((char*)(inBuffer + i), "'0'", 3)) || (!memcmp((char*)(inBuffer + i), "\"0\"", 3)))
+ {
+ nResult = 0;
+ break;
+ }
+ else
+ {
+ nResult = -1;
+ }
+ }
+ }
+ IF_TRUE_RETURN(((i == nSize) || (nResult < 0)), TADC_RESPONSEMESSAGE_ERROR);
+
+ //Init
+ TADC_IF_MemSet(t_RO, 0, sizeof(T_RO));
+ TADC_IF_MemSet(tmpDH_B, 0, sizeof(tmpDH_B));
+ TADC_IF_MemSet(sha1_tmp, 0, sizeof(sha1_tmp));
+ TADC_IF_MemSet(hmacBuf, 0, sizeof(hmacBuf));
+
+ //Check HMAC
+ req_length = 0;
+
+ for (i = 0 ; i < nSize ; i++)
+ {
+ if (!TADC_IF_MemCmp((char*)(inBuffer + i), "<responsedata>", 14))
+ {
+ i += 14;
+ for (j = i ; j < nSize ; j++)
+ {
+ if (!TADC_IF_MemCmp((char*)(inBuffer+j), ";hmac=", 6))
+ {
+ req_length = j-i;
+ IF_TRUE_RETURN(req_length <= 0 || req_length >= RESP_MAXSIZE, TADC_PARAMETER_ERROR);
+
+ ReqTemp = (TADC_U8*)TADC_IF_Malloc(req_length);
+ IF_TRUE_RETURN(ReqTemp == NULL, TADC_MEMAlOC_ERROR);
+
+ TADC_IF_MemSet(ReqTemp, 0, req_length);
+ TADC_IF_MemCpy(ReqTemp, inBuffer+i, req_length);
+
+ i += req_length;
+
+ TADC_IF_StrNCpy(hmacBuf, (char*)(inBuffer + i + 6), nHMacSize);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ IF_TRUE_RETURN(req_length <= 0, TADC_RESPONSEMESSAGE_ERROR);
+
+ pbBuffer = Base64Decode( (LPCSTR)hmacBuf, &length );
+ if (pbBuffer == NULL)
+ {
+ TADC_IF_Free(ReqTemp);
+ ReqTemp = NULL;
+ return -1;
+ }
+
+ TADC_IF_MemCpy(key, &g_baAESKey[0], 16 );
+ TADC_IF_MemCpy(iv, &g_baAESKey[16], 16 );
+ TADC_IF_AES_CTR(16, key, 16, iv, 20, (unsigned char*)pbBuffer, &outlen, (unsigned char*)pbBuffer);
+
+ TADC_IF_SHA1(ReqTemp, req_length, sha1_tmp);
+ if (ReqTemp != NULL)
+ {
+ TADC_IF_Free(ReqTemp);
+ ReqTemp = NULL;
+ }
+
+ if (TADC_IF_MemCmp(sha1_tmp, pbBuffer, sizeof(sha1_tmp)))
+ {
+ TADC_IF_Free(pbBuffer);
+ pbBuffer = NULL;
+ DRM_TAPPS_EXCEPTION("TADC_IF_MemCmp Error Code = %x", TADC_RESPONSESIGNATURE_ERROR);
+ return TADC_RESPONSESIGNATURE_ERROR;
+ }
+
+ TADC_IF_Free(pbBuffer);
+ pbBuffer = NULL;
+
+ req_length = 0;
+
+ for (i = 0 ; i < nSize ; i++)
+ {
+ if (!TADC_IF_MemCmp(inBuffer + i, "B=", 2))
+ {
+ i += 2;
+ for (j = i ; j < nSize ; j++)
+ {
+ if (!TADC_IF_MemCmp(inBuffer + j, ";", 1))
+ {
+ req_length = j - i;
+ IF_TRUE_RETURN(req_length <= 0 || req_length >= (int)sizeof(tmpDH_B), TADC_PARAMETER_ERROR);
+ TADC_IF_StrNCpy((char*)tmpDH_B, (char*)(inBuffer + i), req_length);
+ tmpDH_B[req_length] = 0;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ IF_TRUE_RETURN(req_length <= 0, TADC_RESPONSEMESSAGE_ERROR);
+
+ TADC_IF_MemSet(t_ROAcqInfo->t_DHInfo.B, 0, sizeof(t_ROAcqInfo->t_DHInfo.B));
+ TADC_IF_MemCpy(t_ROAcqInfo->t_DHInfo.B, tmpDH_B, sizeof(t_ROAcqInfo->t_DHInfo.B));
+
+ if (HEX2BIN((char*)tmpDH_B, t_ROAcqInfo->t_DHInfo.B, (int*)&t_ROAcqInfo->t_DHInfo.BSize) < 0)
+ {
+ return TADC_GETDHKEY_ERROR;
+ }
+
+ if(t_ROAcqInfo->t_DHInfo.BSize != 16 && t_ROAcqInfo->t_DHInfo.BSize != 64)
+ {
+ return TADC_GETDHKEY_ERROR;
+ }
+
+ TADC_IF_MemSet(t_ROAcqInfo->t_DHInfo.K, 0, sizeof(t_ROAcqInfo->t_DHInfo.K));
+
+ nResult = TADC_IF_GetDHKey_K(&t_ROAcqInfo->t_DHInfo);
+ IF_ERROR_RETURN(nResult, TADC_GETDHKEY_ERROR);
+
+ req_length = 0;
+
+ for (i = 0 ; i < nSize ; i++)
+ {
+ if (!TADC_IF_MemCmp((char*)(inBuffer + i), "license=", 8))
+ {
+ i += 8;
+ for (j = i ; j < nSize ; j++)
+ {
+ if (!TADC_IF_MemCmp((char*)(inBuffer + j), ";hmac=", 6))
+ {
+ req_length = j - i;
+ IF_TRUE_RETURN(req_length <= 0 || req_length >= RESP_MAXSIZE, TADC_PARAMETER_ERROR);
+
+ License = (char*)TADC_IF_Malloc(req_length + 1);
+ IF_TRUE_RETURN(License == NULL, TADC_MEMAlOC_ERROR);
+
+ TADC_IF_MemSet(License, 0, req_length + 1);
+ TADC_IF_StrNCpy(License, (char*)(inBuffer + i), req_length);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ IF_TRUE_RETURN(req_length <= 0, TADC_RESPONSEMESSAGE_ERROR);
+
+ // Get RO License Info
+ pbBuffer = Base64Decode((LPCSTR)License, &length);
+ if(!pbBuffer)
+ {
+ TADC_IF_Free(License);
+ License = NULL;
+ return -1;
+ }
+
+ pbBuffer[length] = 0;
+ TADC_IF_Free(License);
+ License = NULL;
+
+ // Decrypt License
+ TADC_IF_MemCpy(key, &t_ROAcqInfo->t_DHInfo.K[0], 16);
+ TADC_IF_MemCpy(iv, &t_ROAcqInfo->t_DHInfo.K[16], 16);
+ TADC_IF_AES_CTR(16, key, 16, iv, length, (unsigned char*)pbBuffer, &outlen, (unsigned char*)pbBuffer);
+
+ // Test Code for get the plaintext ro
+ /*
+ strcat(tmpPath, (char*)t_RO->t_Content.CID);
+ strcat(tmpPath, ".ro");
+ fd = fopen(tmpPath, "w+b");
+ */
+#if 0
+ DRM_TAPPS_LOG("fopen started.");
+ fd = fopen("/tmp/1.ro", "w+b");
+ if (fd == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("fopen() failed.");
+ return -1;
+ }
+ DRM_TAPPS_LOG("fopen done.");
+ fwrite(pbBuffer, 1, strlen((char*)pbBuffer), fd);
+ DRM_TAPPS_LOG("fwrite done.");
+ fclose(fd);
+ DRM_TAPPS_LOG("fclose done.");
+ DRM_TAPPS_LOG("Save decrypted RO success!, path = %s", tmpPath);
+#endif
+ // Test Code Done!
+
+ if(TADC_IF_MemCmp((char*)pbBuffer, pRoHeader, 36))
+ {
+ TADC_IF_Free(pbBuffer);
+ pbBuffer = NULL;
+ DRM_TAPPS_EXCEPTION("TADC_IF_MemCmp Error Code = %x", TADC_LICENSEXMLPARSING_ERROR);
+ return TADC_LICENSEXMLPARSING_ERROR;
+ }
+ TADC_IF_MemCpy(outBuffer, pbBuffer, length);
+ TADC_IF_Free(pbBuffer);
+ pbBuffer = NULL;
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // 2011.03.08
+ // Get timeStamp
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ retLen = length;
+ // <timeStamp>
+ req_length = 0;
+
+ DRM_TAPPS_LOG("timeStamp parsing start");
+
+ i = FindString(inBuffer, nSize, (unsigned char *)"<timeStamp>", 11);
+ if (i < 0) {
+ DRM_TAPPS_LOG("No timeStamp. TADC_GetResponseRO Success!");
+ return retLen;
+ }
+
+ i += 11;
+ j = FindString(inBuffer, nSize, (unsigned char *)"</timeStamp>", 12);
+ IF_TRUE_RETURN(j < i, TADC_LICENSEXMLPARSING_ERROR);
+ req_length = j - i;
+ IF_TRUE_RETURN(req_length > ROXML_MAXSIZE, TADC_PARAMETER_ERROR);
+
+ if (req_length <= 0)
+ return retLen;
+
+ timeStamp = (char*)TADC_IF_Malloc(req_length + 1);
+ IF_TRUE_RETURN(timeStamp == NULL, TADC_MEMAlOC_ERROR);
+
+ TADC_IF_MemSet(timeStamp, 0, req_length + 1);
+ TADC_IF_StrNCpy(timeStamp, (char*)(inBuffer + i), req_length);
+
+ DRM_TAPPS_LOG("timeStamp parsing end.. req_length[%d]", req_length);
+
+ // Get RO License Info
+ pbBuffer = Base64Decode((LPCSTR)timeStamp, &length);
+ if (!pbBuffer)
+ {
+ TADC_IF_Free(timeStamp);
+ timeStamp = NULL;
+ DRM_TAPPS_EXCEPTION("Base64Decode Failed");
+ return -1;
+ }
+
+ pbBuffer[length] = 0;
+ TADC_IF_Free(timeStamp);
+ timeStamp = NULL;
+
+ DRM_TAPPS_LOG("Decrypt timeStamp starts");
+
+ // Decrypt timeStamp
+ TADC_IF_MemCpy(key, &t_ROAcqInfo->t_DHInfo.K[0], 16);
+ TADC_IF_MemCpy(iv, &t_ROAcqInfo->t_DHInfo.K[16], 16);
+ TADC_IF_AES_CTR(16, key, 16, iv, length, (unsigned char*)pbBuffer, &outlen, (unsigned char*)pbBuffer);
+
+ if (length >= (int)sizeof(t_ROAcqInfo->sTimeStamp))
+ {
+ TADC_IF_Free(pbBuffer);
+ pbBuffer = NULL;
+ DRM_TAPPS_EXCEPTION("TADC_IF_MemCmp Error Code = %x", TADC_RESPONSEMESSAGE_ERROR);
+ return TADC_RESPONSEMESSAGE_ERROR;
+ }
+
+ TADC_IF_MemCpy(t_ROAcqInfo->sTimeStamp, pbBuffer, length);
+ t_ROAcqInfo->sTimeStamp[length] = 0;
+
+ TADC_IF_Free(pbBuffer);
+ pbBuffer = NULL;
+
+ DRM_TAPPS_LOG("timeStamp found. TADC_GetResponseRO Success!");
+ return retLen;
+}
+
+int TADC_VerifyROSignature(IN LPBYTE pszXML)
+{
+ int nResult = 0;
+ int length = 0, i = 0, i2 = 0;
+
+ unsigned char* pSigData = NULL;
+ unsigned char* pRICert = NULL;
+ unsigned char* pRICACert = NULL;
+
+ int inLen = 0, sigLen = 0, certLen = 0, certLen2 = 0;
+
+ unsigned char* p;
+ char TempBuf[CERT_MAXSIZE] = {0, };
+
+ //Check Param Buffer
+ IF_TRUE_RETURN(pszXML == NULL, TADC_PARAMETER_ERROR);
+
+ //Check Version
+ i = FindString(pszXML, TADC_IF_StrLen((char*)pszXML), (LPBYTE)"<version>2.0</version>", 22);
+ if (i < 0)
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_VerifyROSignature Debug : It is not the TAD-RO2.0 format. \n");
+ return 0;
+ }
+
+ DRM_TAPPS_LOG("TADC_IF_VerifyROSignature Debug : It is the TAD-RO2.0 format.\n");
+
+ //Get Certificates ( RI Cert )
+ TADC_IF_MemSet(TempBuf, 0x00, CERT_MAXSIZE);
+
+ i = FindString(pszXML, TADC_IF_StrLen((char*)pszXML), (LPBYTE)"<CertificateChain>", 18);
+ IF_TRUE_RETURN(i < 0, TADC_RO_CERTIFICATE_ERROR);
+
+ p = pszXML + i; // <certificateChain>
+ length = TADC_IF_StrLen((char*)pszXML) - i;
+
+ i = FindString(p, length, (LPBYTE)"<Certificate>", 13);
+ IF_TRUE_RETURN(i < 0, TADC_RO_CERTIFICATE_ERROR);
+ i += 13; // start position of RI Cert
+
+ i2 = FindString(p, length, (LPBYTE)"</Certificate>", 14);
+ IF_TRUE_RETURN(i2 < (i + 13), TADC_RO_CERTIFICATE_ERROR);
+ certLen = i2 - i; // size of RI Cert
+
+ TADC_IF_StrNCpy(TempBuf, (char*)p+i, certLen);
+
+ pRICert = Base64Decode( (LPCSTR)TempBuf, &certLen );
+ IF_TRUE_RETURN(pRICert == NULL, TADC_RO_CERTIFICATE_ERROR);
+ TADC_IF_MemSet(TempBuf, 0x00, CERT_MAXSIZE);
+
+ //Get Certificates ( RICA Cert )
+ p = p + (i2 + 14); // first </certificate>
+ length = length - (i2 + 14);
+
+ i = FindString(p, length, (LPBYTE)"<Certificate>", 13);
+ IF_TRUE_RETURN2(i < 0, TADC_IF_Free(pRICert),,,TADC_RO_CERTIFICATE_ERROR);
+ i += 13; // start position of RICA Cert
+
+ i2 = FindString(p, length, (LPBYTE)"</Certificate>", 14);
+ IF_TRUE_RETURN2(i2 < (i + 13), TADC_IF_Free(pRICert),,,TADC_RO_CERTIFICATE_ERROR);
+ certLen2 = i2 - i; // size of RICA Cert
+
+ TADC_IF_StrNCpy(TempBuf, (char*)p + i, certLen2);
+
+ pRICACert = Base64Decode((LPCSTR)TempBuf, &certLen2);
+ IF_TRUE_RETURN2(pRICACert == NULL, TADC_IF_Free(pRICert),,,TADC_RO_CERTIFICATE_ERROR);
+ TADC_IF_MemSet(TempBuf, 0x00, CERT_MAXSIZE);
+
+ //Get position of indata
+ inLen = FindString(pszXML, TADC_IF_StrLen((char*)pszXML), (LPBYTE)"</CertificateChain>", 19);
+ IF_TRUE_RETURN2(inLen < 0, TADC_IF_Free(pRICert),TADC_IF_Free(pRICACert),,TADC_RO_CERTIFICATE_ERROR);
+ inLen += 19;
+
+ //Get signature value </certificateChain>
+ p = pszXML + inLen;
+ length = TADC_IF_StrLen((char*)pszXML)-inLen;
+
+ i = FindString(p, length, (LPBYTE)"<SignatureValue>", 16);
+ IF_TRUE_RETURN2(i < 0, TADC_IF_Free(pRICert),TADC_IF_Free(pRICACert),,TADC_RO_SIGNATURE_ERROR);
+ i += 16; // start position of signature value
+
+ i2 = FindString(p, length, (LPBYTE)"</SignatureValue>", 17);
+ IF_TRUE_RETURN2(i2 < (i + 16), TADC_IF_Free(pRICert),TADC_IF_Free(pRICACert),,TADC_RO_SIGNATURE_ERROR);
+ sigLen = i2 - i; // size of signature value
+
+ TADC_IF_StrNCpy(TempBuf, (char*)p + i, sigLen);
+
+ pSigData = Base64Decode( (LPCSTR)TempBuf, &sigLen );
+ IF_TRUE_RETURN2(pSigData == NULL, TADC_IF_Free(pRICert),TADC_IF_Free(pRICACert),,TADC_RO_SIGNATURE_ERROR);
+ TADC_IF_MemSet(TempBuf, 0x00, CERT_MAXSIZE);
+
+ //Verify the certificate chain
+ nResult = TADC_IF_VerifyCertChain(pRICACert, certLen2, pRICert, certLen);
+ if (nResult == 0)
+ {
+ nResult = TADC_IF_VerifySignature(pszXML, inLen, pSigData, sigLen, pRICert, certLen);
+ }
+
+ TADC_IF_Free(pRICert);
+ TADC_IF_Free(pRICACert);
+ TADC_IF_Free(pSigData);
+
+ return nResult;
+}
+
+int TADC_GetResponseROInfo(IN LPBYTE pszXML, T_RO *t_RO)
+{
+ int nResult = 0;
+ CXMLFile oXMLFile;
+ CXMLElement* pRoot, *pElement;
+ CPointerArray paChilds;
+ LPCTSTR pszValue;
+ LPBYTE pbBuffer = NULL;
+ int length = 0;
+ TADC_U8 TempVersion[3] = {0, };
+
+ char pRoHeader[36] = {'<', '?', 'x', 'm', 'l', ' ', 'v', 'e', 'r', 's', 'i', 'o', 'n', '=', '"', '1', '.', '0', '"', '?', '>', 0x0A,
+ '<', 'T', 'i', 'z', 'e', 'n', 'L', 'i', 'c', 'e', 'n', 's', 'e', '>'};
+
+ //Check Param Buffer
+ IF_TRUE_RETURN(pszXML == NULL, TADC_PARAMETER_ERROR);
+ IF_TRUE_RETURN(t_RO == NULL, TADC_PARAMETER_ERROR);
+
+ //Init
+ TADC_IF_MemSet(t_RO, 0, sizeof(T_RO));
+ TADC_IF_MemSet(TempVersion, 0, sizeof(TempVersion));
+
+ if (TADC_IF_MemCmp((char*)pszXML, pRoHeader, 36))
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_MemCmp Error Code = %x", TADC_XMLPARSER_ERROR);
+ return -1;
+ }
+
+ // Verify the signature ( 2011.03.08, Joseph Ahn )
+ nResult = TADC_VerifyROSignature(pszXML);
+ if (nResult != 0)
+ {
+ DRM_TAPPS_EXCEPTION("TADC_VerifyROSignature Error Code = %x", nResult);
+ return -1;
+ }
+
+ nResult = oXMLFile.LoadFromStream((LPCTSTR)pszXML);
+ if (nResult < 0)
+ {
+ DRM_TAPPS_EXCEPTION("oXMLFile.LoadFromStream is failed\n");
+ nResult = -1;
+ goto finish;
+ }
+
+ // Set Version
+ pRoot = oXMLFile.GetRoot();
+ if (pRoot == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("oXMLFile.GetRoot is failed\n");
+ nResult = -1;
+ goto finish;
+ }
+
+ paChilds.RemoveAll();
+ nResult = pRoot->Find( &paChilds, _T("ContentInfo"), _T("cid"), NULL);
+ if (nResult != 0)
+ {
+ DRM_TAPPS_EXCEPTION("pRoot->Find is failed\n");
+ nResult = -1;
+ goto finish;
+ }
+
+ if (paChilds.GetCount() != 1)
+ {
+ DRM_TAPPS_EXCEPTION("paChilds.GetCount() is failed\n");
+ nResult = -1;
+ goto finish;
+ }
+
+ pElement = (CXMLElement*)paChilds.Get(0);
+ pszValue = pElement->GetValue();
+ if (pszValue == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("pElement->GetValue() is failed\n");
+ nResult = -1;
+ goto finish;
+ }
+
+ length = TADC_IF_StrLen((char*)pszValue);
+ if (length <= 0 || length > CID_SIZE)
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_StrLen is failed(%d) - %s\n", length, pszValue);
+ nResult = -1;
+ goto finish;
+ }
+
+ t_RO->t_Content.CID = (TADC_U8*)TADC_IF_Malloc(length + 1); //2011.03.08 ( CID_SIZE -> length )
+ IF_TRUE_GOTO(t_RO->t_Content.CID == NULL, -2);
+ TADC_IF_MemSet(t_RO->t_Content.CID, 0, length + 1); //2011.03.08 ( CID_SIZE -> length )
+ TADC_IF_StrNCpy((CHAR*)t_RO->t_Content.CID, pszValue, length);
+
+ // Get KeyValue (CEK)
+ pRoot = oXMLFile.GetRoot();
+ IF_TRUE_GOTO(pRoot == NULL, ERROR_INVALID_DATA);
+
+ paChilds.RemoveAll();
+ nResult = pRoot->Find( &paChilds, _T("KeyInfo"), _T("CipherValue"), NULL);
+
+ IF_TRUE_GOTO(nResult != 0, ERROR_INVALID_DATA);
+ IF_TRUE_GOTO(paChilds.GetCount() != 1, ERROR_INVALID_DATA);
+
+ pElement = (CXMLElement*)paChilds.Get(0);
+ pszValue = pElement->GetValue();
+ IF_TRUE_GOTO(pszValue == NULL, -2);
+
+ pbBuffer = Base64Decode(pszValue, &length);
+ if (pbBuffer == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_MemCmp Error Code = %x", TADC_XMLPARSER_ERROR);
+ return -1;
+ }
+
+ if (length <= 0 || length > CEK_SIZE)
+ {
+ TADC_IF_Free(pbBuffer);
+ pbBuffer = NULL;
+ nResult = -1;
+ goto finish;
+ }
+
+ t_RO->t_Content.CEK = (TADC_U8*)TADC_IF_Malloc(length + 1); //2011.03.08 ( CEK_SIZE -> length )
+ IF_TRUE_GOTO(t_RO->t_Content.CEK == NULL, -2);
+ TADC_IF_MemSet(t_RO->t_Content.CEK, 0, length + 1); //2011.03.08 ( CEK_SIZE -> length )
+ TADC_IF_MemCpy(t_RO->t_Content.CEK, pbBuffer, length);
+
+ TADC_IF_Free(pbBuffer);
+ pbBuffer = NULL;
+
+ // Get individual
+ pRoot = oXMLFile.GetRoot();
+ IF_TRUE_GOTO(pRoot == NULL, ERROR_INVALID_DATA);
+
+ paChilds.RemoveAll();
+ nResult = pRoot->Find( &paChilds, _T("DeviceInfo"), _T("DUID"), NULL);
+
+ IF_TRUE_GOTO(nResult != 0, ERROR_INVALID_DATA);
+ IF_TRUE_GOTO(paChilds.GetCount() != 1, ERROR_INVALID_DATA);
+
+ pElement = (CXMLElement*)paChilds.Get(0);
+ pszValue = pElement->GetValue();
+ IF_TRUE_GOTO(pszValue == NULL, -1);
+ length = TADC_IF_StrLen((char*)pszValue);
+ if (length <= 0)
+ {
+ nResult = -1;
+ goto finish;
+ }
+
+ t_RO->PerFlag |= DUID_RULE;
+ t_RO->t_Permission.t_Individual.BindingType |= DUID_RULE;
+ t_RO->t_Permission.t_Individual.DUID = (TADC_U8*)TADC_IF_Malloc(length + 1);
+
+ if (t_RO->t_Permission.t_Individual.DUID == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_MemCmp Error Code = %x", TADC_MEMAlOC_ERROR);
+ }
+
+ TADC_IF_MemSet(t_RO->t_Permission.t_Individual.DUID, 0, length + 1);
+ TADC_IF_MemCpy((CHAR*)t_RO->t_Permission.t_Individual.DUID, pszValue, length);
+
+ nResult = 0;
+
+finish:
+ pszValue = NULL;
+
+ if (nResult < 0)
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_MemCmp Error Code = %x", TADC_XMLPARSER_ERROR);
+ }
+
+ if (nResult == -2)
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_MemCmp Error Code = %x", TADC_MEMAlOC_ERROR);
+ }
+
+ TADC_IF_Free(pbBuffer);
+
+ return nResult;
+}
+
+int TADC_GetFileHeader(unsigned char * inBuffer, T_FILE_HEADER *t_FileHeader)
+{
+ int i = 0;
+ BYTE FixedFileType[8] = {0x00,0x00,0x00,0x14,0x66,0x74,0x79,0x70};
+ char tmp[2];
+
+ //Check Param Bufffer
+ IF_TRUE_RETURN(inBuffer == NULL, TADC_PARAMETER_ERROR);
+ IF_TRUE_RETURN(t_FileHeader == NULL, TADC_PARAMETER_ERROR);
+
+ //Init
+ TADC_IF_MemSet(t_FileHeader, 0, sizeof(T_FILE_HEADER));
+ TADC_IF_MemSet(tmp, 0, sizeof(tmp));
+
+ if (TADC_IF_MemCmp(inBuffer, FixedFileType, sizeof(FixedFileType)))
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_MemCmp Error Code = %x", TADC_CONTENTSSTRUCT_ERROR);
+ return -1;
+ }
+ i += 8;
+
+ if (TADC_IF_MemCmp(inBuffer+i, "TADF", 4))
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_MemCmp Error Code = %x", TADC_CONTENTSSTRUCT_ERROR);
+ return -2;
+ }
+ i += 4;
+
+ t_FileHeader->Version[0] = '1';
+ t_FileHeader->Version[1] = '0';
+ i += 4;
+
+ if (TADC_IF_MemCmp(inBuffer+i, "TADF", 4))
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_MemCmp Error Code = %x", TADC_CONTENTSSTRUCT_ERROR);
+ return -2;
+ }
+ i += 4;
+
+ t_FileHeader->DRMType = inBuffer[i];
+ i += 1;
+
+ TADC_IF_MemCpy(t_FileHeader->ContentsType, inBuffer+i, 128);
+ i += 128;
+
+ TADC_IF_MemCpy(&t_FileHeader->TotalSize, inBuffer+i, 8);
+ i += 8;
+ t_FileHeader->TotalSize = _hton64(t_FileHeader->TotalSize);
+
+ TADC_IF_MemCpy(&t_FileHeader->Offset1, inBuffer+i, 8);
+ i += 8;
+ t_FileHeader->Offset1 = _hton64(t_FileHeader->Offset1);
+
+ TADC_IF_MemCpy(&t_FileHeader->Offset2, inBuffer+i, 8);
+ i += 8;
+ t_FileHeader->Offset2 = _hton64(t_FileHeader->Offset2);
+
+ TADC_IF_MemCpy(&t_FileHeader->Offset3, inBuffer+i, 8);
+ i += 8;
+ t_FileHeader->Offset3 = _hton64(t_FileHeader->Offset3);
+
+ TADC_IF_MemCpy(&t_FileHeader->Offset4, inBuffer+i, 8);
+ i += 8;
+ t_FileHeader->Offset4 = _hton64(t_FileHeader->Offset4);
+
+ TADC_IF_MemCpy(&t_FileHeader->Offset5, inBuffer+i, 8);
+ i += 8;
+ t_FileHeader->Offset5 = _hton64(t_FileHeader->Offset5);
+
+ TADC_IF_MemCpy(&t_FileHeader->Offset6, inBuffer+i, 8);
+ i += 8;
+ t_FileHeader->Offset6 = _hton64(t_FileHeader->Offset6);
+
+ TADC_IF_MemCpy(&t_FileHeader->Offset7, inBuffer+i, 8);
+ i += 8;
+ t_FileHeader->Offset7 = _hton64(t_FileHeader->Offset7);
+
+ TADC_IF_MemCpy(&t_FileHeader->Offset8, inBuffer+i, 8);
+ i += 8;
+ t_FileHeader->Offset8 = _hton64(t_FileHeader->Offset8);
+
+ DRM_TAPPS_LOG("TADC_GetFileHeader Success!\n");
+ return 0;
+}
+
+int TADC_GetDRMHeader(unsigned char * inBuffer, T_DRM_HEADER *t_DRMHeader)
+{
+ int i = 0;
+
+ //Check Param Bufffer
+ IF_TRUE_RETURN(inBuffer == NULL, TADC_PARAMETER_ERROR);
+ IF_TRUE_RETURN(t_DRMHeader == NULL, TADC_PARAMETER_ERROR);
+
+ //Init
+ TADC_IF_MemSet(t_DRMHeader, 0, sizeof(T_DRM_HEADER));
+
+ if (TADC_IF_MemCmp(inBuffer, "TIZEN_DRM", 9))
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_MemCmp Error Code = %x", TADC_NOTTADCFILE_ERROR);
+ return -1;
+ }
+ i += 9;
+
+ TADC_IF_MemCpy(t_DRMHeader->Version, inBuffer+i, 2);
+ i += 2;
+
+ TADC_IF_MemCpy(&t_DRMHeader->XmlSize, inBuffer+i, 4);
+ i += 4;
+
+ t_DRMHeader->XmlSize = htonl_(t_DRMHeader->XmlSize);
+ DRM_TAPPS_LOG("TADC_GetDRMHeader Success!\n");
+
+ return 0;
+}
+
+int TADC_GetDRMHeaderInfo(unsigned char * inBuffer, T_DRM_HEADER *t_DRMHeader)
+{
+ int nResult = 0;
+ CXMLFile oXMLFile;
+ CXMLElement* pRoot, *pNode;
+ CPointerArray paChilds;
+ LPCTSTR pszValue;
+
+ BYTE sha1_tmp[20];
+ unsigned char *ReqTemp=NULL;
+
+ TADC_U8 key[16];
+ TADC_U8 iv[16];
+
+ int outlen=0;
+ long Length=0;
+
+ //Check Param
+ IF_TRUE_RETURN(inBuffer == NULL, TADC_PARAMETER_ERROR);
+ IF_TRUE_RETURN(t_DRMHeader == NULL, TADC_PARAMETER_ERROR);
+
+ IF_TRUE_RETURN(t_DRMHeader->XmlSize <= 0 || t_DRMHeader->XmlSize > ROXML_MAXSIZE, TADC_PARAMETER_ERROR);
+
+ ReqTemp = (TADC_U8*)TADC_IF_Malloc(t_DRMHeader->XmlSize);
+ IF_TRUE_RETURN(ReqTemp == NULL, TADC_MEMAlOC_ERROR);
+
+ TADC_IF_MemSet(ReqTemp, 0, t_DRMHeader->XmlSize);
+ TADC_IF_MemSet(sha1_tmp, 0, sizeof(sha1_tmp) );
+
+ //Get HMAC
+ TADC_IF_MemCpy(ReqTemp, inBuffer + 20, t_DRMHeader->XmlSize);
+ TADC_IF_SHA1(ReqTemp, t_DRMHeader->XmlSize, sha1_tmp);
+
+ if (ReqTemp != NULL)
+ {
+ TADC_IF_Free(ReqTemp);
+ ReqTemp = NULL;
+ }
+
+ TADC_IF_MemCpy(key, &g_baSignatureKey[0], 16);
+ TADC_IF_MemCpy(iv, &g_baSignatureKey[16], 16);
+ TADC_IF_AES_CTR(16, key, 16, iv, 20, (unsigned char*)sha1_tmp, &outlen, (unsigned char*)sha1_tmp);
+
+ if (TADC_IF_MemCmp(sha1_tmp, inBuffer, sizeof(sha1_tmp)))
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_MemCmp Error Code = %x", TADC_CONTENTSHMAC_ERROR);
+ return -1;
+ }
+
+ //Load XML Header
+ nResult = oXMLFile.LoadFromStream((LPCTSTR)(inBuffer + 20));
+
+ if (nResult != 0)
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_MemCmp Error Code = %x", TADC_CONTENTSXML_ERROR);
+ goto finish;
+ }
+
+ pRoot = oXMLFile.GetRoot();
+ IF_TRUE_GOTO( pRoot == NULL, ERROR_INVALID_DATA );
+
+ paChilds.RemoveAll();
+ nResult = pRoot->Find( &paChilds, _T("SID"), NULL );
+
+ if (nResult == 0)
+ {
+ if (paChilds.GetCount() == 1)
+ {
+ pNode = (CXMLElement*)paChilds.Get(0);
+ pszValue = pNode->GetValue();
+ Length = TADC_IF_StrLen((char*)pszValue);
+
+ if (Length > 0)
+ {
+ t_DRMHeader->SID = (TADC_U8*)TADC_IF_Malloc(Length + 1);
+ IF_TRUE_RETURN(t_DRMHeader->SID == NULL, TADC_MEMAlOC_ERROR);
+ TADC_IF_MemSet(t_DRMHeader->SID, 0, Length + 1);
+ TADC_IF_StrNCpy((CHAR*)t_DRMHeader->SID, pszValue, Length);
+ }
+ }
+ }
+
+ pRoot = oXMLFile.GetRoot();
+ IF_TRUE_GOTO( pRoot == NULL, ERROR_INVALID_DATA );
+
+ paChilds.RemoveAll();
+ nResult = pRoot->Find( &paChilds, _T("CID"), NULL );
+
+ if (nResult == 0)
+ {
+ if (paChilds.GetCount() == 1)
+ {
+ pNode = (CXMLElement*)paChilds.Get(0);
+ pszValue = pNode->GetValue();
+ Length = TADC_IF_StrLen((char*)pszValue); //2011.03.08
+
+ if (Length > 0)
+ {
+ t_DRMHeader->CID = (TADC_U8*)TADC_IF_Malloc(Length + 1); //2011.03.08 ( CID_SIZE -> Length )
+ IF_TRUE_RETURN(t_DRMHeader->CID == NULL, TADC_MEMAlOC_ERROR);
+ TADC_IF_MemSet(t_DRMHeader->CID, 0, Length + 1); //2011.03.08 ( CID_SIZE -> Length )
+ TADC_IF_StrNCpy((CHAR*)t_DRMHeader->CID, pszValue, Length); //2011.03.08 ( CID_SIZE -> Length )
+ }
+ }
+ }
+
+ pRoot = oXMLFile.GetRoot();
+ IF_TRUE_GOTO(pRoot == NULL, ERROR_INVALID_DATA);
+ paChilds.RemoveAll();
+ nResult = pRoot->Find(&paChilds, _T("ContentType"), NULL);
+
+ if (nResult == 0)
+ {
+ if (paChilds.GetCount() == 1)
+ {
+ pNode = (CXMLElement*)paChilds.Get(0);
+ pszValue = pNode->GetValue();
+ Length = TADC_IF_StrLen((char*)pszValue);
+ TADC_IF_MemSet(t_DRMHeader->ContentsType, 0, 128);
+ TADC_IF_StrNCpy((CHAR*)t_DRMHeader->ContentsType, pszValue, Length);
+ }
+ }
+
+ pRoot = oXMLFile.GetRoot();
+ IF_TRUE_GOTO( pRoot == NULL, ERROR_INVALID_DATA );
+ paChilds.RemoveAll();
+ nResult = pRoot->Find( &paChilds, _T("EncryptionMethod"), NULL );
+
+ if (nResult == 0)
+ {
+ if (paChilds.GetCount() == 1)
+ {
+ pNode = (CXMLElement*)paChilds.Get(0);
+ pszValue = pNode->GetValue();
+ t_DRMHeader->EncryptionMethod = TADC_IF_AtoI((char*)pszValue);
+ }
+ }
+
+ pRoot = oXMLFile.GetRoot();
+ IF_TRUE_GOTO( pRoot == NULL, ERROR_INVALID_DATA );
+ paChilds.RemoveAll();
+ nResult = pRoot->Find( &paChilds, _T("EncryptionLevel"), NULL );
+
+ if (nResult == 0)
+ {
+ if (paChilds.GetCount() == 1)
+ {
+ pNode = (CXMLElement*)paChilds.Get(0);
+ pszValue = pNode->GetValue();
+ t_DRMHeader->EncryptionLevel = TADC_IF_AtoI((char*)pszValue);
+ }
+ }
+
+ pRoot = oXMLFile.GetRoot();
+ IF_TRUE_GOTO( pRoot == NULL, ERROR_INVALID_DATA );
+ paChilds.RemoveAll();
+ nResult = pRoot->Find( &paChilds, _T("EncryptionRange"), NULL );
+
+ if (nResult == 0)
+ {
+ if (paChilds.GetCount() == 1)
+ {
+ pNode = (CXMLElement*)paChilds.Get(0);
+ pszValue = pNode->GetValue();
+ t_DRMHeader->EncryptionRange = TADC_IF_AtoI((char*)pszValue);
+ }
+ }
+
+ pRoot = oXMLFile.GetRoot();
+ IF_TRUE_GOTO( pRoot == NULL, ERROR_INVALID_DATA );
+ paChilds.RemoveAll();
+ nResult = pRoot->Find( &paChilds, _T("RIURL"), NULL );
+
+ if (nResult == 0)
+ {
+ if (paChilds.GetCount() == 1)
+ {
+ pNode = (CXMLElement*)paChilds.Get(0);
+ pszValue = pNode->GetValue();
+ Length = TADC_IF_StrLen((char*)pszValue);
+
+ if (Length > 0)
+ {
+ t_DRMHeader->RIURL = (TADC_U8*)TADC_IF_Malloc(Length+1);
+ IF_TRUE_RETURN(t_DRMHeader->RIURL == NULL, TADC_MEMAlOC_ERROR);
+ TADC_IF_MemSet(t_DRMHeader->RIURL, 0, Length+1);
+ TADC_IF_StrNCpy((CHAR*)t_DRMHeader->RIURL, pszValue, Length);
+ }
+ }
+ }
+
+ // dummy RIURL(DRM Server spec changed)
+ if (t_DRMHeader->RIURL == NULL)
+ {
+ pszValue = "dummy_riurl";
+ Length = TADC_IF_StrLen(pszValue);
+ t_DRMHeader->RIURL = (TADC_U8*)TADC_IF_Malloc(Length+1);
+ IF_TRUE_RETURN(t_DRMHeader->RIURL == NULL, TADC_MEMAlOC_ERROR);
+ TADC_IF_MemSet(t_DRMHeader->RIURL, 0, Length+1);
+ TADC_IF_StrNCpy((CHAR*)t_DRMHeader->RIURL, pszValue, Length);
+ }
+
+ DRM_TAPPS_LOG("t_DRMHeader->RIURL = %s\n", (char*)t_DRMHeader->RIURL);
+
+ pRoot = oXMLFile.GetRoot();
+ IF_TRUE_GOTO( pRoot == NULL, ERROR_INVALID_DATA );
+ paChilds.RemoveAll();
+ nResult = pRoot->Find( &paChilds, _T("PlaintextSize"), NULL );
+
+ if (nResult == 0)
+ {
+ if (paChilds.GetCount() == 1)
+ {
+ pNode = (CXMLElement*)paChilds.Get(0);
+ pszValue = pNode->GetValue();
+ t_DRMHeader->PlaintextSize = TADC_IF_AtoI((char*)pszValue);
+ }
+ }
+
+ pRoot = oXMLFile.GetRoot();
+ IF_TRUE_GOTO( pRoot == NULL, ERROR_INVALID_DATA );
+ paChilds.RemoveAll();
+ nResult = pRoot->Find( &paChilds, _T("Packdate"), NULL );
+
+ if (nResult == 0)
+ {
+ if (paChilds.GetCount() == 1)
+ {
+ pNode = (CXMLElement*)paChilds.Get(0);
+ pszValue = pNode->GetValue();
+ Length = TADC_IF_StrLen((char*)pszValue);
+
+ if (Length > 0)
+ {
+ t_DRMHeader->Packdate = (TADC_U8*)TADC_IF_Malloc(Length+1);
+ IF_TRUE_RETURN(t_DRMHeader->Packdate == NULL, TADC_MEMAlOC_ERROR);
+ TADC_IF_MemSet(t_DRMHeader->Packdate, 0, Length+1);
+ TADC_IF_StrNCpy((char*)t_DRMHeader->Packdate, pszValue, Length);
+ }
+ }
+ }
+
+finish:
+ if (nResult != 0)
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_MemCmp Error Code = %x", TADC_CONTENTSXML_ERROR);
+ STACKTRACE( _T( "CNCG20File::_ParseHeader()" ) );
+ }
+ DRM_TAPPS_LOG("TADC_GetDRMHeaderInfo Success! \n");
+ return nResult;
+}
+
+int TADC_GetCEK(T_DEVICE_INFO *t_DeviceInfo, T_RO *t_RODB, T_DRM_HEADER *t_DRMHeader)
+{
+ int length1 = 0;
+
+ //Check Parameter Buffer
+ IF_TRUE_RETURN(t_DeviceInfo == NULL, TADC_PARAMETER_ERROR);
+ IF_TRUE_RETURN(t_DRMHeader == NULL, TADC_PARAMETER_ERROR);
+ IF_TRUE_RETURN(t_DRMHeader->CID == NULL, TADC_PARAMETER_ERROR);
+ IF_TRUE_RETURN(t_RODB == NULL, TADC_PARAMETER_ERROR);
+ IF_TRUE_RETURN(t_RODB->t_Content.CID == NULL, TADC_PARAMETER_ERROR);
+
+ if(!TADC_IF_StrCmp((char*)t_DRMHeader->CID, (char*)t_RODB->t_Content.CID)) //2011.03.08 ( TADC_IF_MemCmp -> TADC_IF_StrCmp )
+ {
+ if((t_RODB->PerFlag & DUID_RULE) && (t_RODB->t_Permission.t_Individual.BindingType & DUID_RULE))
+ {
+ IF_TRUE_RETURN(t_RODB->t_Permission.t_Individual.DUID == NULL, TADC_PARAMETER_ERROR);
+ length1 = TADC_IF_StrLen((char*)t_DeviceInfo->DUID);
+ DRM_TAPPS_LOG("t_DeviceInfo->DUID = %s, t_RODB->t_Permission.t_Individual.DUID is %s, length1 is %d\n", t_DeviceInfo->DUID, t_RODB->t_Permission.t_Individual.DUID, length1);
+ /*if(TADC_IF_MemCmp(t_DeviceInfo->DUID, t_RODB->t_Permission.t_Individual.DUID, length1))
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_MemCmp Error Code = %x", TADC_RULE_DUID_ERROR);
+ return -1;
+ } */
+ }
+ IF_TRUE_RETURN(t_RODB->t_Content.CEK == NULL, TADC_PARAMETER_ERROR);
+ t_DRMHeader->CEK = (TADC_U8*)TADC_IF_Malloc(CEK_SIZE + 1);
+ IF_TRUE_RETURN(t_DRMHeader->CEK == NULL, TADC_MEMAlOC_ERROR);
+ TADC_IF_MemSet(t_DRMHeader->CEK, 0, CEK_SIZE + 1);
+ TADC_IF_MemCpy(t_DRMHeader->CEK, t_RODB->t_Content.CEK, CEK_SIZE);
+
+ DRM_TAPPS_LOG("TADC_GetCEK Success!\n");
+ return 0;
+ }
+
+ DRM_TAPPS_EXCEPTION("TADC_IF_MemCmp Error Code = %x", TADC_RULE_NOINFOMATION);
+
+ return -1;
+}
+
+int TADC_DecryptBlock( char* pbBuffer, int nSize, T_DRM_HEADER *t_DRMHeader)
+{
+ TADC_U8 key[16] = {0, };
+ TADC_U8 iv[16] = {0, };
+ int i = 0, nBlocks = 0, nIndex = 0;
+ char baToBeEncrypted[32] = {0, };
+ int nRemainBytes = 0, nBlockBytes = 0;
+
+ int nEncryptionLevel = 0;
+ int nEncryptionMethod = 0;
+
+ char temp[512] = {0, };
+ int length = 0;
+ int totlength = 0;
+
+ TADC_IF_MemSet(temp, 0, sizeof(temp));
+
+ IF_TRUE_RETURN(pbBuffer == NULL, TADC_PARAMETER_ERROR);
+ IF_TRUE_RETURN(t_DRMHeader == NULL, TADC_PARAMETER_ERROR);
+
+ IF_TRUE_RETURN(nSize > 512, TADC_PARAMETER_ERROR);
+ IF_TRUE_RETURN(t_DRMHeader->CEK == NULL, TADC_PARAMETER_ERROR);
+
+ nEncryptionLevel = t_DRMHeader->EncryptionLevel;
+ nEncryptionMethod = t_DRMHeader->EncryptionMethod;
+
+ IF_TRUE_RETURN(nEncryptionMethod != 1, TADC_PARAMETER_ERROR);
+ IF_TRUE_RETURN(nEncryptionLevel < 0 || nEncryptionLevel > 32, TADC_PARAMETER_ERROR);
+
+ TADC_IF_MemSet( baToBeEncrypted, 1, 32 );
+
+ if (nEncryptionLevel > 16)
+ {
+ nBlocks = 16;
+ }
+ else
+ {
+ nBlocks = nEncryptionLevel;
+ }
+
+ for (i = 0 ; i < nBlocks ; i++)
+ {
+ nIndex = 31 - (i * 2);
+ baToBeEncrypted[nIndex] = 0;
+ }
+
+ for (i = 16 ; i < nEncryptionLevel ; i++)
+ {
+ nIndex = 30 - ((i - 16) * 2);
+ baToBeEncrypted[nIndex] = 0;
+ }
+
+ nRemainBytes = nSize;
+ nBlockBytes = 16;
+
+ length = 0;
+ totlength = 0;
+
+ for (i = 0 ; i < 32 ; i++)
+ {
+ if (nRemainBytes < 16)
+ {
+ nBlockBytes = nRemainBytes;
+ }
+
+ if (baToBeEncrypted[i] == 1)
+ {
+ TADC_IF_MemCpy(temp + length, pbBuffer + totlength, nBlockBytes);
+ length += nBlockBytes;
+ }
+
+ nRemainBytes -= nBlockBytes;
+ totlength += nBlockBytes;
+
+ if (nRemainBytes < 1)
+ {
+ break;
+ }
+ }
+
+ TADC_IF_MemCpy(key, &t_DRMHeader->CEK[0], 16);
+ TADC_IF_MemCpy(iv, &t_DRMHeader->CEK[16], 16);
+ TADC_IF_AES_CTR(16, key, 16, iv, length, (unsigned char*)temp, &length, (unsigned char*)temp);
+
+ nRemainBytes = nSize;
+ nBlockBytes = 16;
+
+ length = 0;
+ totlength = 0;
+
+ for (i = 0 ; i < 32 ; i++)
+ {
+ if (nRemainBytes < 16)
+ {
+ nBlockBytes = nRemainBytes;
+ }
+
+ if (baToBeEncrypted[i] == 1)
+ {
+ TADC_IF_MemCpy(pbBuffer + totlength, temp + length, nBlockBytes);
+ length += nBlockBytes;
+ }
+
+ nRemainBytes -= nBlockBytes;
+ totlength += nBlockBytes;
+
+ if (nRemainBytes < 1)
+ {
+ break;
+ }
+ }
+ return 0;
+}
+
+int TADC_GetDRMHeaderFromFile(const char *pTADCFilepath, T_FILE_HEADER *t_FileHeader, T_DRM_HEADER *t_DRMHeader )
+{
+
+ unsigned char tempbuf[512];
+ unsigned char *pbuf = NULL;
+
+ int ret=0;
+ ULONG readsize=0, ReadLen=0;
+
+ FILE * hFile = 0; //Apps drm file
+
+ //null check
+ if (pTADCFilepath == NULL || t_FileHeader == NULL || t_DRMHeader == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("Error : Parameter Null.");
+ return -1;
+ }
+
+ //Init
+ TADC_IF_MemSet(tempbuf, 0, sizeof(tempbuf));
+
+ //File Open
+ if ((hFile = fopen(pTADCFilepath, "rb")) == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("Error : fopen() error.");
+ return -1;
+ }
+
+ readsize = 256;
+
+ //FmReadFile(hFile, tempbuf, readsize, &ReadLen);
+ ReadLen = fread(tempbuf, 1, readsize, hFile);
+ if ((readsize != ReadLen) || (ret=TADC_GetFileHeader(tempbuf, t_FileHeader)) < 0)
+ {
+ DRM_TAPPS_EXCEPTION("Error : fread() error.");
+ fclose(hFile);
+ return -1;
+ }
+ TADC_IF_MemSet(tempbuf, 0, sizeof(tempbuf));
+
+ //Tizen Apps DRM Type Check
+ if (t_FileHeader->DRMType & TIZEN_DRM)
+ {
+ DRM_TAPPS_LOG("It's a TAPPS DCF = %s", pTADCFilepath);
+ readsize = 15;
+ ReadLen = fread(tempbuf, 1, readsize, hFile);
+ if ((readsize != ReadLen) || (ret=TADC_GetDRMHeader(tempbuf, t_DRMHeader)) < 0)
+ {
+ DRM_TAPPS_EXCEPTION("Error : fread() error.");
+ fclose(hFile);
+ return -1;
+ }
+
+ readsize = 20 + t_DRMHeader->XmlSize;
+ if ((pbuf = (unsigned char*)TADC_IF_Malloc( readsize * sizeof(char))) == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("Error : fread() error.");
+ fclose(hFile);
+ return -1;
+ }
+
+ ReadLen = fread(pbuf, 1, readsize, hFile);
+ if (readsize != ReadLen)
+ {
+ DRM_TAPPS_EXCEPTION("Error : fread() error.");
+ TADC_IF_Free(pbuf);
+ fclose(hFile);
+ return -1;
+ }
+
+ if (TADC_GetDRMHeaderInfo(pbuf, t_DRMHeader) < 0)
+ {
+ DRM_TAPPS_EXCEPTION("Error : TADC_GetDRMHeaderInfo error.");
+ TADC_IF_Free(pbuf);
+ fclose(hFile);
+ return -1;
+ }
+ TADC_IF_Free(pbuf);
+ }
+ else
+ {
+ DRM_TAPPS_EXCEPTION("Error : It's not a TApps DCF file.");
+ fclose(hFile);
+ return -1;
+ }
+
+ fclose(hFile);
+ return 0;
+}
+
+DWORD TADC_GetLastError(void)
+{
+ DWORD dwError = g_TADCErrorCode;
+ g_TADCErrorCode = 0;
+
+ return dwError;
+}
+
+int TADC_MEMFree_RO(T_RO *t_ro)
+{
+ IF_TRUE_RETURN(t_ro == NULL, TADC_PARAMETER_ERROR);
+ t_ro->PerFlag = 0;
+
+ if (t_ro->t_Content.CID != NULL)
+ {
+ TADC_IF_Free(t_ro->t_Content.CID);
+ t_ro->t_Content.CID = NULL;
+ }
+
+ if (t_ro->t_Content.CEK!= NULL)
+ {
+ TADC_IF_Free(t_ro->t_Content.CEK);
+ t_ro->t_Content.CEK = NULL;
+ }
+
+ if (t_ro->t_Permission.t_Individual.DUID != NULL)
+ {
+ TADC_IF_Free(t_ro->t_Permission.t_Individual.DUID);
+ t_ro->t_Permission.t_Individual.DUID = NULL;
+ }
+
+ return 0;
+}
+
+int TADC_MEMFree_FileHeader(T_FILE_HEADER *t_FileHeader)
+{
+ IF_TRUE_RETURN(t_FileHeader == NULL, TADC_PARAMETER_ERROR);
+ TADC_IF_MemSet(t_FileHeader, 0, sizeof(T_FILE_HEADER));
+
+ return 0;
+}
+
+int TADC_MEMFree_DRMHeader(T_DRM_HEADER *t_DrmHeader)
+{
+ IF_TRUE_RETURN(t_DrmHeader == NULL, TADC_PARAMETER_ERROR);
+ t_DrmHeader->XmlSize = 0;
+ TADC_IF_MemSet(t_DrmHeader->Version, 0, sizeof(t_DrmHeader->Version));
+
+ if (t_DrmHeader->SID != NULL)
+ {
+ TADC_IF_Free(t_DrmHeader->SID);
+ t_DrmHeader->SID = NULL;
+ }
+
+ if (t_DrmHeader->CID != NULL)
+ {
+ TADC_IF_Free(t_DrmHeader->CID);
+ t_DrmHeader->CID = NULL;
+ }
+
+ TADC_IF_MemSet(t_DrmHeader->ContentsType, 0, sizeof(t_DrmHeader->ContentsType));
+ t_DrmHeader->EncryptionRange = 0;
+
+ if (t_DrmHeader->RIURL != NULL)
+ {
+ TADC_IF_Free(t_DrmHeader->RIURL);
+ t_DrmHeader->RIURL = NULL;
+ }
+
+ t_DrmHeader->PlaintextSize = 0;
+ if (t_DrmHeader->Packdate != NULL)
+ {
+ TADC_IF_Free(t_DrmHeader->Packdate);
+ t_DrmHeader->Packdate = NULL;
+ }
+
+ if (t_DrmHeader->CEK != NULL)
+ {
+ TADC_IF_Free(t_DrmHeader->CEK);
+ t_DrmHeader->CEK = NULL;
+ }
+ return 0;
+}
+
+int TADC_MEMFree_ROAcqInfo(T_ROACQ_INFO *t_ROAcqInfo)
+{
+ IF_TRUE_RETURN(t_ROAcqInfo == NULL, TADC_PARAMETER_ERROR);
+
+ if (t_ROAcqInfo->ROAcqURL != NULL)
+ {
+ TADC_IF_Free(t_ROAcqInfo->ROAcqURL);
+ t_ROAcqInfo->ROAcqURL = NULL;
+ }
+
+ if (t_ROAcqInfo->ReqID != NULL)
+ {
+ TADC_IF_Free(t_ROAcqInfo->ReqID);
+ t_ROAcqInfo->ReqID = NULL;
+ }
+
+ TADC_IF_MemSet(&t_ROAcqInfo->t_DHInfo, 0, sizeof(T_DH_INFO));
+ return 0;
+}
diff --git a/tadcore/TADCCore/TADC_Sub.cpp b/tadcore/TADCCore/TADC_Sub.cpp
new file mode 100644
index 0000000..685299d
--- /dev/null
+++ b/tadcore/TADCCore/TADC_Sub.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 "TADC_Sub.h"
+
+unsigned int htons_(unsigned int hostshort)
+{
+ BYTE *pBuffer;
+ unsigned int nResult;
+
+ nResult = 0;
+ pBuffer = (LPBYTE)&hostshort;
+ nResult = (((pBuffer[0] << 8) & 0xFF00) | (pBuffer[1] & 0x00FF));
+
+ return nResult;
+}
+
+DWORD htonl_(DWORD hostlong)
+{
+ DWORD nResult = hostlong >> 16;
+ unsigned int upper = (unsigned int)nResult & 0x0000FFFF;
+ unsigned int lower = (unsigned int)hostlong & 0x0000FFFF;
+
+ upper = htons_(upper);
+ lower = htons_(lower);
+ nResult = 0x10000 * lower + upper;
+
+ return nResult;
+}
+
+INT64 _hton64( INT64 n64host )
+{
+ INT64 result;
+ LPBYTE p;
+ short n64Test;
+ int n32High, n32Low;
+
+ static int isLittleEndian = -1;
+
+ if( isLittleEndian == -1 )
+ {
+ n64Test = 0x01;
+ p = (LPBYTE)&n64Test;
+
+ if( p[ 0 ] == 0x01 )
+ {
+ isLittleEndian = 1;
+ }
+ else
+ {
+ isLittleEndian = 0;
+ }
+ }
+
+ if( isLittleEndian == 1 )
+ {
+ n32Low = (INT32)( n64host & 0xFFFFFFFF );
+ n32High = (INT32)( n64host >> 32 );
+
+ n32Low = htonl_( n32Low );
+ n32High = htonl_( n32High );
+
+ result = ( (INT64)n32Low << 32 ) | n32High;
+ return result;
+ }
+ else
+ {
+ return n64host;
+ }
+}
diff --git a/tadcore/TADCCore/TADC_Util.cpp b/tadcore/TADCCore/TADC_Util.cpp
new file mode 100644
index 0000000..3bbd235
--- /dev/null
+++ b/tadcore/TADCCore/TADC_Util.cpp
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 "TADC_Core.h"
+#include "TADC_Util.h"
+#include "TADC_Sub.h"
+#include "TADC_IF.h"
+#include "TADC_ErrorCode.h"
+
+// -------------------------- Base64 --------------------------------
+static CHAR __base64_table[] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
+};
+
+static int __reverse_table[] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
+ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+static CHAR __base64_pad = '=';
+
+LPSTR Base64Encode( LPBYTE pbData, int nLength )
+{
+ int i = 0, result = 0;
+ LPSTR pszResult = NULL;
+
+ if (nLength <= 0)
+ {
+ return NULL;
+ }
+ result = ( ( nLength + 3 - nLength % 3 ) * 4 / 3 + 1 );
+
+ pszResult = (LPSTR)TADC_IF_Malloc( result );
+
+ if (pszResult == NULL)
+ {
+ return NULL;
+ }
+
+ TADC_IF_MemSet(pszResult, 0x00, result);
+
+ i = 0;
+
+ while (nLength > 2)
+ {
+ /* keep going until we have less than 24 bits */
+ pszResult[ i++ ] = __base64_table[ pbData[ 0 ] >> 2 ];
+ pszResult[ i++ ] = __base64_table[ ( ( pbData[ 0 ] & 0x03 ) << 4 ) + ( pbData[ 1 ] >> 4 ) ];
+ pszResult[ i++ ] = __base64_table[ ( ( pbData[ 1 ] & 0x0f ) << 2 ) + ( pbData[ 2 ] >> 6 ) ];
+ pszResult[ i++ ] = __base64_table[ pbData[ 2 ] & 0x3f ];
+
+ pbData += 3;
+ nLength -= 3; /* we just handle 3 octets of data */
+ }
+
+ /* now deal with the tail end of things */
+ if (nLength != 0)
+ {
+ pszResult[ i++ ] = __base64_table[ pbData[ 0 ] >> 2 ];
+ if (nLength == 1)
+ {
+ pszResult[ i++ ] = __base64_table[ ( pbData[ 0 ] & 0x03 ) << 4 ];
+ pszResult[ i++ ] = __base64_pad;
+ pszResult[ i++ ] = __base64_pad;
+ }
+ else
+ {
+ pszResult[ i++ ] = __base64_table[ ( ( pbData[ 0 ] & 0x03 ) << 4 ) + ( pbData[ 1 ] >> 4 ) ];
+ pszResult[ i++ ] = __base64_table[ ( pbData[ 1 ] & 0x0f ) << 2 ];
+ pszResult[ i++ ] = __base64_pad;
+ }
+ }
+ pszResult[ i ] = 0;
+ return pszResult;
+}
+
+LPBYTE Base64Decode(LPCSTR pszString, int* pnLength)
+{
+ int result = 0;
+ LPBYTE pbResult = NULL;
+ int nStrLength = 0, i = 0, nOutputLength = 0;
+ BYTE b1, b2, b3, b4;
+
+ nStrLength = TADC_IF_StrLen(pszString);
+ if (nStrLength % 4 != 0)
+ {
+ result = -1;
+ goto finish;
+ }
+
+ pbResult = (LPBYTE)TADC_IF_Malloc(nStrLength + 1);
+ if (pbResult == NULL)
+ {
+ return NULL;
+ }
+ TADC_IF_MemSet(pbResult, 0x00, nStrLength + 1);
+
+ nOutputLength = 0;
+
+ for (i = 0 ; i < nStrLength ; i += 4)
+ {
+ b1 = (BYTE)__reverse_table[ pszString[ i ] ];
+ b2 = (BYTE)__reverse_table[ pszString[ i + 1 ] ];
+ b3 = (BYTE)__reverse_table[ pszString[ i + 2 ] ];
+ b4 = (BYTE)__reverse_table[ pszString[ i + 3 ] ];
+
+ pbResult[ nOutputLength++ ] = (BYTE)( ( b1 << 2 ) | ( b2 >> 4 ) );
+
+ if (pszString[ i + 2 ] == '=')
+ {
+ pbResult[ nOutputLength ] = (BYTE)( ( b2 & 0x0F ) << 4 );
+ }
+ else
+ {
+ pbResult[ nOutputLength++ ] = (BYTE)( ( ( b2 & 0x0F ) << 4 ) | ( b3 >> 2 ) );
+
+ if (pszString[ i + 3 ] == '=')
+ {
+ pbResult[ nOutputLength ] = (BYTE)( ( b3 & 0x03 ) << 6 );
+ }
+ else
+ {
+ pbResult[ nOutputLength++ ] = (BYTE)( ( ( b3 & 0x03 ) << 6 ) | b4 );
+ }
+ }
+ }
+ *pnLength = nOutputLength;
+ result = 0;
+
+finish:
+ if (result != 0)
+ {
+ TADC_IF_Free( pbResult );
+ }
+
+ return pbResult;
+}
+// -------------------------- Base64 --------------------------------]]]]
+
+int HEX2BIN(LPCSTR pszHex, LPBYTE baBin, int* pnLength )
+{
+ CHAR szTemp[ 3 ];
+ CHAR szHex[ 1024 ];
+ int i = 0, nLength = 0;
+
+ nLength = TADC_IF_StrLen(pszHex);
+
+ if (nLength <= 0)
+ {
+ return -1;
+ }
+
+ if ((nLength % 2) == 0)
+ {
+ TADC_IF_StrNCpy(szHex, pszHex, nLength);
+ }
+ else
+ {
+ szHex[ 0 ] = '0';
+ TADC_IF_StrNCpy(&szHex[ 1 ], pszHex, nLength);
+ nLength += 1;
+ }
+
+ *pnLength = nLength / 2;
+ szTemp[ 2 ] = 0;
+
+ for (i = 0 ; i < *pnLength ; i++ )
+ {
+ szTemp[ 0 ] = szHex[ i * 2 ];
+ szTemp[ 1 ] = szHex[ i * 2 + 1 ];
+ baBin[ i ] = (BYTE)strtoul( szTemp, NULL, 16 );
+ }
+ return 0;
+}
+
+//Find String (2011.03.08)
+//return : start position of find string or error (-1)
+int FindString(unsigned char *in, int inLen, unsigned char *find, int findLen)
+{
+ int i = 0;
+
+ for (i = 0 ; i <= inLen - findLen ; i++)
+ {
+ if (!TADC_IF_MemCmp(in + i, find, findLen))
+ return i;
+ }
+ return -1;
+}
diff --git a/tadcore/TADCInterface/DUIDGenerator.cpp b/tadcore/TADCInterface/DUIDGenerator.cpp
new file mode 100644
index 0000000..43ddacb
--- /dev/null
+++ b/tadcore/TADCInterface/DUIDGenerator.cpp
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// 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 DUIDGenerator.cpp
+ * @brief This is the implementation file for get_id.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <device_info.h>
+
+#include "DUIDGenerator.h"
+#include "drm-tizen-mid.h"
+
+int get_duid(char **duid)
+{
+ const char *device_id = NULL;
+
+ if (duid == NULL) {
+ DRM_TAPPS_EXCEPTION("Invalid argument.");
+ return -1;
+ }
+
+ device_id = get_device_id();
+ if (device_id == NULL) {
+ DRM_TAPPS_EXCEPTION("Failed to generate DUID.");
+ return -1;
+ }
+
+ *duid = strdup(device_id);
+ DRM_TAPPS_LOG("DUID is [%s].", *duid);
+
+ return 0;
+}
diff --git a/tadcore/TADCInterface/TADC_IF.cpp b/tadcore/TADCInterface/TADC_IF.cpp
new file mode 100644
index 0000000..122291e
--- /dev/null
+++ b/tadcore/TADCInterface/TADC_IF.cpp
@@ -0,0 +1,551 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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.
+ */
+
+//#define _SLP_SIMUL
+#include "TADC_IF.h"
+#include "TADC_Util.h"
+#include "TADC_ErrorCode.h"
+
+#include "drm_intf_tapps.h"
+
+#include <openssl/aes.h>
+#include <openssl/sha.h>
+#include <openssl/dh.h>
+#include <openssl/bn.h>
+
+//2011.03.08 to verify signature
+#include <openssl/x509.h>
+#include <openssl/x509_vfy.h>
+#include <openssl/evp.h>
+#include <openssl/rsa.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+
+#include <dirent.h>
+
+#include "DUIDGenerator.h"
+
+
+int TADC_IF_GetDUID(char *Duid)
+{
+ if (!Duid) {
+ DRM_TAPPS_EXCEPTION("Invalid argument.");
+ return TADC_GETDUID_ERROR;
+ }
+
+ char *duid = NULL;
+ if (get_duid(&duid) < 0 || !duid) {
+ DRM_TAPPS_EXCEPTION("Failed to get DUID.");
+ return TADC_GETDUID_ERROR;
+ }
+
+ DRM_TAPPS_LOG("DUID is [%s]", duid);
+ memcpy(Duid, duid, strlen(duid) + 1);
+
+ free(duid);
+
+ return TADC_SUCCESS;
+}
+
+int TADC_IF_GetDHKey(T_DH_INFO *t_dhinfo)
+{
+ DH *pDH = NULL;
+ TADC_IF_MemSet(t_dhinfo, 0, sizeof(t_dh_info));
+
+ // Debug
+ DRM_TAPPS_LOG("Debug Log == TADC_IF_GetDHKey : After TADC_IF_MemSet(t_dhinfo, 0, sizeof(t_dh_info))");
+
+ //1. dh new
+ if ((pDH = DH_new()) == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("DH_new() error!");
+ return -1;
+ }
+
+ // Debug
+ DRM_TAPPS_LOG("Debug Log == TADC_IF_GetDHKey : After DH_new");
+
+ //2. Set the Prime and Generator Value
+ BYTE prime64[64] = {
+ 0xAE, 0xD9, 0x65, 0x3C, 0x86, 0x3E, 0xD9, 0x6F, 0x31, 0x6E,
+ 0xF6, 0x08, 0x35, 0xD5, 0x01, 0xC1, 0x41, 0x2E, 0xDD, 0x7E,
+ 0xE9, 0x09, 0x99, 0x73, 0xF3, 0xB3, 0xAB, 0x1F, 0x80, 0x85,
+ 0x44, 0x22, 0xDA, 0x07, 0x32, 0x18, 0xC1, 0xF8, 0xC4, 0xED,
+ 0x9F, 0x66, 0x88, 0xCF, 0xD6, 0x18, 0x8B, 0x28, 0x56, 0xA5,
+ 0xB3, 0x6A, 0x8E, 0xBB, 0xC4, 0x2B, 0x2B, 0x3A, 0x9C, 0x20,
+ 0x4E, 0xF7, 0x7F, 0xC3 };
+ BYTE generator[1] = {DH_GENERATOR_5};
+
+ pDH->p = BN_bin2bn(prime64, 64, NULL);
+ pDH->g = BN_bin2bn(generator, 1, NULL);
+
+ /* Set a to run with normal modexp and b to use constant time */
+ pDH->flags &= ~DH_FLAG_NO_EXP_CONSTTIME;
+
+ // Debug
+ DRM_TAPPS_LOG("Debug Log == TADC_IF_GetDHKey : After Set the Prime and Generator Value");
+
+ //3. Generate DH Key
+ if (!DH_generate_key(pDH))
+ {
+ DRM_TAPPS_EXCEPTION("DH_generate_key() error!");
+ return -1;
+ }
+
+ // Debug
+ DRM_TAPPS_LOG("Debug Log == TADC_IF_GetDHKey : After DH_generate_key");
+
+ //4. Save DH Infos ( p, g, A, a )
+ TADC_IF_MemCpy(t_dhinfo->p, prime64, 64);
+ t_dhinfo->pSize = 64;
+ t_dhinfo->g = DH_GENERATOR_5;
+ t_dhinfo->ASize = BN_bn2bin(pDH->pub_key, t_dhinfo->A);
+ t_dhinfo->aSize = BN_bn2bin(pDH->priv_key, t_dhinfo->a);
+
+ //5. DH Free
+ DH_free(pDH);
+
+ // Debug
+ DRM_TAPPS_LOG("Debug Log == TADC_IF_GetDHKey : After DH_free");
+
+ return 0;
+}
+
+int TADC_IF_GetDHKey_K(T_DH_INFO *t_dhinfo)
+{
+ DH *pDH = NULL;
+ BIGNUM *pPubKey = NULL;
+
+ char tempbuf[DHKey_SIZE + 1];
+ int i = 0;
+
+ unsigned char tempG[1];
+
+ TADC_IF_MemSet(tempbuf, 0, sizeof(tempbuf));
+
+ //1. dh new
+ if ((pDH = DH_new()) == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("DH_new() error!");
+ return -1;
+ }
+
+ //2.Set DH Info to pDH
+ pDH->p = BN_bin2bn(t_dhinfo->p, t_dhinfo->pSize, NULL);
+ tempG[0] = t_dhinfo->g;
+ pDH->g = BN_bin2bn(tempG, 1, NULL);
+ pDH->flags &= ~DH_FLAG_NO_EXP_CONSTTIME;
+ pDH->pub_key = BN_bin2bn(t_dhinfo->A, t_dhinfo->ASize, NULL);
+ pDH->priv_key = BN_bin2bn(t_dhinfo->a, t_dhinfo->aSize, NULL);
+
+ //3. Set Public Key of Server
+ pPubKey = BN_bin2bn(t_dhinfo->B, t_dhinfo->BSize, NULL);
+
+ //4. Compute DH Session Key
+ if ((i = DH_compute_key((BYTE*)tempbuf, pPubKey, pDH)) < 0)
+ {
+ DRM_TAPPS_EXCEPTION("DH_compute_key() error! \n");
+ return -1;
+ }
+
+ for (i = 0 ; i < (t_dhinfo -> BSize / 2) ; i++)
+ {
+ t_dhinfo->K[i] = tempbuf[i * 2] ^ tempbuf[(i * 2) + 1];
+ }
+
+ //5. DH Free
+ DH_free(pDH);
+ BN_free(pPubKey);
+
+ return 0;
+}
+
+int TADC_IF_AES_CTR(int keyLen, unsigned char *pKey, int ivLen, unsigned char *pIV, int inLen, unsigned char *in, int *pOutLen, unsigned char *out)
+{
+ AES_KEY stKey;
+ UINT num;
+ TADC_U8 ecount[16];
+ TADC_U8 chain[16];
+
+ AES_set_encrypt_key(pKey, 128, &stKey);
+
+ num = 0;
+
+ TADC_IF_MemSet(ecount, 0, sizeof(ecount));
+ TADC_IF_MemSet(chain, 0, sizeof(chain));
+ TADC_IF_MemCpy(chain, pIV, ivLen);
+
+ AES_ctr128_encrypt(in, out, inLen, &stKey, chain, ecount, &num);
+
+ *pOutLen = inLen;
+
+ return 0;
+}
+
+int TADC_IF_SHA1(unsigned char *in, int inLen, unsigned char *out)
+{
+ SHA_CTX AlgInfo;
+
+ SHA1_Init(&AlgInfo);
+ SHA1_Update(&AlgInfo, in, inLen);
+ SHA1_Final(out, &AlgInfo);
+
+ return 0;
+}
+
+int TADC_IF_VerifySignature( unsigned char* inData, int inLen,
+ unsigned char* sigData, int sigLen,
+ unsigned char* cert, int certLen )
+{
+ unsigned char hashValue[20];
+ int iRet = 0;
+
+ X509* pX509 = NULL;
+ EVP_PKEY* pKey = NULL;
+ RSA* pRsa = NULL;
+
+ //Check parameters
+ if (inData == NULL || sigData == NULL || cert == NULL || inLen < 1 || sigLen < 1 || certLen < 1)
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_VerifySignature Error : Parameter error!");
+ return -1;
+ }
+
+ iRet = 0;
+
+ //1. Make Hash value of indata by using SHA1
+ TADC_IF_SHA1(inData, inLen, hashValue);
+
+ //2. Get RSA Public Key from cert data ( DER )
+ pX509 = d2i_X509(NULL, (const unsigned char**)&cert, certLen);
+ if (pX509 == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_VerifySignature Error : Get RSA Public Key from cert data!");
+ return -1;
+ }
+
+ pKey = X509_get_pubkey(pX509);
+ if (pKey == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_VerifySignature Error : X509_get_pubkey!");
+ return -1;
+ }
+
+ pRsa = EVP_PKEY_get1_RSA(pKey);
+ if (pRsa == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_VerifySignature Error : EVP_PKEY_get1_RSA!");
+ if (NULL != pKey)
+ {
+ EVP_PKEY_free(pKey);
+ }
+ return -1;
+ }
+
+ //3. Verify RSA Sign
+ iRet = RSA_verify(NID_sha1, hashValue, 20, sigData, sigLen, pRsa);
+ if (1 != iRet)
+ {
+ int err = 0;
+ char tmpBuf[120] = {0,};
+
+ while ((err = ERR_get_error()) != 0)
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_VerifySignature Error : RSA_verify error(%s)", ERR_error_string(err, tmpBuf));
+ }
+ //Error
+ //DRM_TAPPS_EXCEPTION("TADC_IF_VerifySignature Error : RSA_verify error(%s)", ERR_error_string(ERR_get_error(), NULL));
+
+ if (NULL != pKey)
+ {
+ EVP_PKEY_free(pKey);
+ }
+
+ return -1;
+ }
+
+ //free
+ if (NULL != pKey)
+ {
+ EVP_PKEY_free(pKey);
+ }
+
+ return 0;
+}
+
+int AddCertUntrustedCerts(STACK_OF(X509)* untrustedCerts, unsigned char* cert, int certLen)
+{
+ X509* pstX509 = NULL;
+
+ if (untrustedCerts == NULL || cert == NULL || certLen < 1)
+ {
+ DRM_TAPPS_EXCEPTION("AddCertSTORE Error : Parameter error!");
+ return -1;
+ }
+
+ pstX509 = d2i_X509(NULL, (const unsigned char **) &cert, certLen);
+ if (pstX509 == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("AddCertSTORE Error : d2i_X509 error!");
+ return -1;
+ }
+
+ sk_X509_push(untrustedCerts, pstX509);
+
+ return 0;
+}
+
+int AddCertSTOREFromFile(X509_STORE* pstStore, const char* filePath)
+{
+ X509* pstX509 = NULL;
+ FILE* file = NULL;
+ int ret = 0;
+
+ file = fopen(filePath, "r");
+ if(!file)
+ {
+ DRM_TAPPS_EXCEPTION("AddCertSTOREFromFile Error : Parameter error! Fail to open a cert file.");
+ ret = -1;
+ goto error;
+ }
+
+ pstX509 = PEM_read_X509(file, NULL, NULL, NULL);
+ if (pstX509 == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("AddCertSTORE Error : d2i_X509 error!");
+ ret = -1;
+ goto error;
+ }
+
+ X509_STORE_add_cert(pstStore, pstX509);
+
+error:
+ if(file!=NULL)
+ fclose(file);
+ return ret;
+}
+
+int AddCertSTOREFromDir(X509_STORE* pstStore, const char* dirPath)
+{
+ int ret = 0;
+
+ DIR *dir = NULL;
+ struct dirent entry;
+ struct dirent *result;
+ int error;
+ char file_path_buff[512];
+
+ if (pstStore == NULL || dirPath == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("AddCertSTOREFromDir Error : Parameter error!");
+ ret = -1;
+ goto error;
+ }
+
+ dir = opendir(dirPath);
+ if(dir == NULL) {
+ DRM_TAPPS_EXCEPTION("AddCertSTOREFromDir Error : cannot open directory!");
+ ret = -1;
+ goto error;
+ }
+
+ for(;;) {
+ error = readdir_r(dir, &entry, &result);
+ if( error != 0 ) {
+ DRM_TAPPS_EXCEPTION("AddCertSTOREFromDir Error : fail to read entries from a directory!");
+ ret = -1;
+ goto error;
+ }
+ // readdir_r returns NULL in *result if the end
+ // of the directory stream is reached
+ if(result == NULL)
+ break;
+
+ if(entry.d_type == DT_REG) { // regular file
+ memset(file_path_buff, 0, sizeof(file_path_buff));
+ snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s", dirPath, entry.d_name);
+ if(AddCertSTOREFromFile(pstStore, file_path_buff) == 0) {
+ DRM_TAPPS_LOG("Add root cert : file=%s", file_path_buff);
+ }else {
+ DRM_TAPPS_LOG("Fail to add root cert : file=%s", file_path_buff);
+ }
+ }
+ }
+
+error:
+ if(dir!=NULL)
+ closedir(dir);
+ return ret;
+}
+
+int TADC_IF_VerifyCertChain( unsigned char* rica, int ricaLen,
+ unsigned char* cert, int certLen )
+{
+ X509_STORE_CTX* pstStoreCtx = NULL;
+ X509_STORE* pstStore = NULL;
+ STACK_OF(X509)* untrustedCerts = NULL;
+
+ X509* pstX509 = NULL;
+
+ int iRet = 0;
+ int iErrCode = 0;
+
+ //must call this function.
+ OpenSSL_add_all_algorithms();
+
+ pstStore = X509_STORE_new();
+ if(pstStore == NULL)
+ {
+ iRet = -1;
+ goto error;
+ }
+
+ untrustedCerts = sk_X509_new_null();
+ if(untrustedCerts == NULL)
+ {
+ iRet = -1;
+ goto error;
+ }
+
+
+ //Add RICA Cert to certchain
+ if ((iRet = AddCertUntrustedCerts(untrustedCerts, rica, ricaLen)) != 0)
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_VerifyCertChain Error : Add RICA Cert to certchain!");
+ iRet = -1;
+ goto error;
+ }
+
+ //Add Root CA Cert
+ if ((iRet = AddCertSTOREFromDir(pstStore, RO_ISSUER_ROOT_CERTS_DIR)) != 0)
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_VerifyCertChain Error : Add Root CA Cert!");
+ iRet = -1;
+ goto error;
+ }
+
+ //Get Cert
+ pstX509 = d2i_X509(NULL, (const unsigned char **)&cert, certLen);
+
+ if (pstX509 == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_VerifyCertChain Error : Get Cert d2i_X509 error!");
+ iRet = -1;
+ goto error;
+ }
+
+ X509_STORE_set_flags(pstStore, X509_V_FLAG_CB_ISSUER_CHECK);
+ pstStoreCtx = X509_STORE_CTX_new();
+ if (pstStoreCtx == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_VerifyCertChain Error : 509_STORE_CTX_new error!");
+ iRet = -1;
+ goto error;
+ }
+
+ //init
+ X509_STORE_CTX_init(pstStoreCtx, pstStore, pstX509, untrustedCerts);
+
+ //Set Flag
+ X509_STORE_CTX_set_flags(pstStoreCtx, X509_V_FLAG_CB_ISSUER_CHECK);
+
+ //verify
+ iRet = X509_verify_cert(pstStoreCtx);
+
+ //free
+error:
+ if (pstStore != NULL)
+ X509_STORE_free(pstStore);
+ if (pstStoreCtx != NULL)
+ X509_STORE_CTX_free(pstStoreCtx);
+ if (untrustedCerts != NULL)
+ sk_X509_free(untrustedCerts);
+
+ if (iRet == 1)
+ {
+ DRM_TAPPS_LOG("TADC_IF_VerifyCertChain Success! \n");
+ return 0;
+ }
+ else if (iRet == 0)
+ {
+ iErrCode = X509_STORE_CTX_get_error(pstStoreCtx);
+ DRM_TAPPS_EXCEPTION("TADC_IF_VerifyCertChain Error : %s \n", X509_verify_cert_error_string(iErrCode));
+ return -1;
+ }
+ else
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_VerifyCertChain Error : 509_verify_cert error! \n");
+ return -1;
+ }
+}
+
+size_t TADC_IF_StrLen(const char *string)
+{
+ return strlen(string);
+}
+
+int TADC_IF_StrCmp(const char *string1, const char *string2)
+{
+ return strcmp(string1, string2);
+}
+
+int TADC_IF_StrNCmp(const char *string1, const char *string2, size_t count)
+{
+ return strncmp(string1, string2, count);
+}
+
+char *TADC_IF_StrNCpy(char *strDestination, const char *strSource, size_t count)
+{
+ return strncpy(strDestination, strSource, count);
+}
+
+unsigned long TADC_IF_StrtOul(const char *nptr, char **endptr, int base)
+{
+ return strtoul(nptr, endptr, base);
+}
+
+int TADC_IF_MemCmp(const void *buf1, const void *buf2, size_t count)
+{
+ return memcmp(buf1, buf2, count);
+}
+
+void TADC_IF_MemCpy(void *dest, const void *src, size_t count)
+{
+ memcpy(dest, src, count);
+}
+
+void TADC_IF_MemSet(void *dest, int c, size_t count)
+{
+ memset(dest, c, count);
+}
+
+void *TADC_IF_Malloc(size_t size)
+{
+ return malloc(size);
+}
+
+void TADC_IF_Free(void *memblock)
+{
+ if(memblock != NULL)
+ {
+ free(memblock);
+ }
+}
+
+int TADC_IF_AtoI(char *str)
+{
+ return atoi(str);
+}
diff --git a/tadcore/XMLParser/CPointerArray.cpp b/tadcore/XMLParser/CPointerArray.cpp
new file mode 100644
index 0000000..681f225
--- /dev/null
+++ b/tadcore/XMLParser/CPointerArray.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 "CPointerArray.h"
+#include "TADC_IF.h"
+#include "TADC_ErrorCode.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+#define BUFFER_INC_SIZE 128
+
+CPointerArray::CPointerArray()
+{
+ m_ppData = NULL;
+ m_nMaxSize = 0;
+ m_nNumOfData = 0;
+}
+
+CPointerArray::~CPointerArray()
+{
+ if( m_ppData != NULL )
+ {
+ delete[] m_ppData;
+ }
+}
+
+int CPointerArray::Add( LPVOID pData )
+{
+ int nResult;
+ int nNewSize;
+ LPVOID* ppTemp;
+
+ if( m_ppData == NULL )
+ {
+ m_nMaxSize = BUFFER_INC_SIZE;
+ m_ppData = new LPVOID[ BUFFER_INC_SIZE ];
+
+ if(m_ppData == NULL)
+ {
+ nResult = -1;
+
+ goto finish;
+ }
+ }
+
+ if( m_nNumOfData >= m_nMaxSize )
+ {
+ nNewSize = m_nMaxSize += BUFFER_INC_SIZE;
+ ppTemp = new LPVOID[ nNewSize ];
+ IF_TRUE_GOTO( ppTemp == NULL, -1 );
+
+ memcpy( ppTemp, m_ppData, BUFFER_INC_SIZE * sizeof( LPVOID ) );
+
+ delete[] m_ppData;
+
+ m_nMaxSize += BUFFER_INC_SIZE;
+ m_ppData = ppTemp;
+ }
+
+ m_ppData[ m_nNumOfData ] = pData;
+ m_nNumOfData++;
+
+ nResult = 0;
+
+finish:
+
+ if( nResult != 0 )
+ {
+ DRM_TAPPS_EXCEPTION("CPointerArray::Add() Error! \n");
+ }
+
+ return nResult;
+}
+
+int CPointerArray::Remove( int nIndex )
+{
+ int nResult;
+ int i;
+
+ if( ( nIndex < 0 ) || ( nIndex >= m_nNumOfData ) )
+ {
+ nResult = -1;//ERRORMSG( ERROR_INVALID_PARAMETER, NULL );
+
+ goto finish;
+ }
+
+ for( i = nIndex ; i < m_nNumOfData - 1 ; i++ )
+ {
+ m_ppData[ i ] = m_ppData[ i + 1 ];
+ }
+
+ m_nNumOfData--;
+
+ nResult = 0;
+
+finish:
+
+ if( nResult != 0 )
+ {
+ DRM_TAPPS_EXCEPTION("CPointerArray::Remove() Error! \n");
+ }
+
+ return nResult;
+}
+
+LPVOID CPointerArray::Get( int nIndex )
+{
+ if( ( nIndex < 0 ) || ( nIndex >= m_nNumOfData ) )
+ {
+ return NULL;
+ }
+
+ return m_ppData[ nIndex ];
+}
diff --git a/tadcore/XMLParser/CXMLAttribute.cpp b/tadcore/XMLParser/CXMLAttribute.cpp
new file mode 100644
index 0000000..a6c6fa0
--- /dev/null
+++ b/tadcore/XMLParser/CXMLAttribute.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 "CXMLAttribute.h"
+#include "TADC_IF.h"
+#include "TADC_ErrorCode.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CXMLAttribute::CXMLAttribute()
+ : m_pszName(NULL)
+ , m_pszValue(NULL)
+{}
+
+CXMLAttribute::~CXMLAttribute()
+{
+ if (m_pszName)
+ delete []m_pszName;
+
+ if (m_pszValue)
+ delete []m_pszValue;
+}
+
+// [in] pszName : should be null-terminated string
+int CXMLAttribute::SetName(LPCTSTR pszName)
+{
+ int nResult = 0;
+ size_t pszNameLen = 0;
+
+ if (m_pszName) {
+ delete []m_pszName;
+ m_pszName = NULL;
+ }
+
+ pszNameLen = strlen(pszName);
+
+ m_pszName = new CHAR[pszNameLen + 1];
+ IF_TRUE_GOTO(m_pszName == NULL, ERROR_NOT_ENOUGH_MEMORY);
+
+ memcpy(m_pszName, pszName, pszNameLen + 1);
+
+finish:
+ if (nResult)
+ DRM_TAPPS_EXCEPTION("CXMLAttribute::SetName() Error!");
+
+ return nResult;
+}
+
+// [in] pszValue : should be null-terminated string
+int CXMLAttribute::SetValue(LPCTSTR pszValue)
+{
+ int nResult = 0;
+ size_t pszValueLen = 0;
+
+ if (m_pszValue) {
+ delete []m_pszValue;
+ m_pszValue = NULL;
+ }
+
+ pszValueLen = strlen(pszValue);
+
+ m_pszValue = new CHAR[pszValueLen + 1];
+ IF_TRUE_GOTO(m_pszName == NULL, ERROR_NOT_ENOUGH_MEMORY);
+
+ memcpy(m_pszValue, pszValue, pszValueLen + 1);
+
+finish:
+ if (nResult)
+ DRM_TAPPS_EXCEPTION("CXMLAttribute::SetValue() Error!");
+
+ return nResult;
+}
diff --git a/tadcore/XMLParser/CXMLElement.cpp b/tadcore/XMLParser/CXMLElement.cpp
new file mode 100644
index 0000000..bcfdf5e
--- /dev/null
+++ b/tadcore/XMLParser/CXMLElement.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 "CXMLElement.h"
+
+#include "TADC_IF.h"
+#include "TADC_ErrorCode.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CXMLElement::CXMLElement()
+ : m_pszName(NULL)
+ , m_pszValue(NULL)
+{}
+
+CXMLElement::~CXMLElement()
+{
+ if (m_pszName)
+ delete[] m_pszName;
+
+ if (m_pszValue)
+ delete[] m_pszValue;
+
+ for (int i = 0; i < m_pAttributes.GetCount(); i++)
+ delete (CXMLAttribute *)m_pAttributes.Get(i);
+
+ for (int i = 0; i < m_pChilds.GetCount(); i++)
+ delete (CXMLElement *)m_pChilds.Get(i);
+}
+
+int CXMLElement::SetName(LPCTSTR pszName)
+{
+ int nResult = 0;
+ size_t pszNameLen = 0;
+
+ IF_TRUE_GOTO(pszName == NULL, TADC_PARAMETER_ERROR);
+ pszNameLen = strlen(pszName);
+
+ m_pszName = new CHAR[pszNameLen + 1];
+ IF_TRUE_GOTO(m_pszName == NULL, TADC_MEMAlOC_ERROR);
+
+ memcpy(m_pszName, pszName, pszNameLen + 1);
+
+finish:
+ if (nResult)
+ DRM_TAPPS_EXCEPTION("CXMLElement::SetName() Error!");
+
+ return nResult;
+}
+
+int CXMLElement::SetValue(LPCTSTR pszValue)
+{
+ int nResult = 0;
+ size_t pszValueLen = 0;
+
+ IF_TRUE_GOTO(pszValue == NULL, TADC_PARAMETER_ERROR);
+ pszValueLen = strlen(pszValue);
+
+ m_pszValue = new CHAR[pszValueLen + 1];
+ IF_TRUE_GOTO(m_pszValue == NULL, TADC_MEMAlOC_ERROR);
+
+ memcpy(m_pszValue, pszValue, pszValueLen + 1);
+
+finish:
+ if (nResult)
+ DRM_TAPPS_EXCEPTION("CXMLElement::SetValue() Error!");
+
+ return nResult;
+}
+
+int CXMLElement::AddAttribute(LPCTSTR pszName, LPCTSTR pszValue)
+{
+ int nResult = 0;
+ CXMLAttribute *pAttribute = NULL;
+
+ pAttribute = new CXMLAttribute;
+ IF_TRUE_GOTO(pAttribute == NULL, TADC_MEMAlOC_ERROR);
+
+ pAttribute->SetName(pszName);
+ pAttribute->SetValue(pszValue);
+
+ m_pAttributes.Add(pAttribute);
+
+finish:
+ if (nResult)
+ DRM_TAPPS_EXCEPTION("CXMLElement::AddAttribute() Error!");
+
+ return nResult;
+}
+
+int CXMLElement::AddChild(CXMLElement *pChild)
+{
+ int nResult = 0;
+
+ m_pChilds.Add(pChild);
+
+ return nResult;
+}
+
+int CXMLElement::Find(CPointerArray *pSearchedChild, LPCTSTR pszChildName, ...)
+{
+ int nResult = 0;;
+ va_list args;
+
+ va_start(args, pszChildName);
+
+ nResult = _SearchNodes(pSearchedChild, this, pszChildName, args);
+
+ if (nResult)
+ goto finish;
+
+finish:
+ if (nResult)
+ DRM_TAPPS_EXCEPTION("CXMLElement::Find() Error!");
+
+ va_end(args);
+ return nResult;
+}
+
+int CXMLElement::_SearchNodes(CPointerArray* ppaChildNodes, CXMLElement* pCurrent, LPCTSTR pszTagName, va_list args)
+{
+ int nResult = 0;
+
+ CXMLElement *pChild = NULL;
+ LPCTSTR pszName = NULL;
+ LPCTSTR pszNextName = NULL;
+
+ IF_TRUE_GOTO((!ppaChildNodes || !pCurrent || !pszTagName), TADC_MEMAlOC_ERROR);
+
+ pszNextName = va_arg(args, LPCTSTR);
+
+ for (int i = 0; i < pCurrent->GetChildCount(); i++) {
+ pChild = pCurrent->GetChild(i);
+
+ if (pChild)
+ pszName = pChild->GetName();
+
+ if (pszName && strcasecmp(pszName, pszTagName) == 0) {
+ if (!pszNextName)
+ ppaChildNodes->Add(pChild);
+ else
+ nResult = _SearchNodes(ppaChildNodes, pChild, pszNextName, args);
+ }
+ }
+
+ nResult = 0;
+
+finish:
+ if (nResult)
+ DRM_TAPPS_EXCEPTION("CXMLElement::_SearchNodes() Error!");
+
+ return nResult;
+}
+
+LPCTSTR CXMLElement::GetAttribute(LPCTSTR pszName)
+{
+ CXMLAttribute *pAttribute;
+ LPCTSTR pszValue = NULL;
+
+ for (int i = 0; i < m_pAttributes.GetCount(); i++) {
+ pAttribute = (CXMLAttribute *)m_pAttributes.Get(i);
+
+ if (pAttribute && TADC_IF_StrCmp(pAttribute->GetName(), pszName) == 0) {
+ pszValue = pAttribute->GetValue();
+ break;
+ }
+ }
+
+ return pszValue;
+}
diff --git a/tadcore/XMLParser/CXMLFile.cpp b/tadcore/XMLParser/CXMLFile.cpp
new file mode 100644
index 0000000..f4b32c0
--- /dev/null
+++ b/tadcore/XMLParser/CXMLFile.cpp
@@ -0,0 +1,424 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 "CXMLFile.h"
+#include "TADC_IF.h"
+#include "TADC_ErrorCode.h"
+
+#define _tcsstr strstr
+#define _tcschr strchr
+
+#define _MAX_NAME_LENGTH 4096
+#define _MAX_VALUE_LENGTH 4096
+
+
+#define _SKIP_WHITESPACE() while( ( *m_pszXML == ' ' ) || \
+ ( *m_pszXML == '\n' ) || \
+ ( *m_pszXML == '\r' ) || \
+ ( *m_pszXML == 0x09 ) ) m_pszXML++
+
+typedef struct _tagESCAPE_CHARSET
+{
+ LPCTSTR pszEscape;
+ TCHAR chReplace;
+} T_ESCAPE_CHARSET;
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CXMLFile::CXMLFile()
+{
+ m_nQueueIndex = 0;
+ m_pRoot = NULL;
+
+ for (int i = 0; i < ELEMENT_QUEUE_MAX; ++i)
+ m_paElementQueue[i] = NULL;
+
+ m_pszXML = NULL;
+}
+
+CXMLFile::~CXMLFile()
+{
+ if (m_pRoot)
+ delete m_pRoot;
+}
+
+int CXMLFile::LoadFromStream(LPCTSTR pszXML)
+{
+ int nResult = 0;
+
+ m_nQueueIndex = 0;
+
+ if (m_pRoot)
+ delete m_pRoot;
+
+ m_pRoot = NULL;
+ m_pszXML = pszXML;
+
+ nResult = _Parse();
+
+ if (nResult)
+ goto finish;
+
+finish:
+ if (nResult)
+ DRM_TAPPS_EXCEPTION("CXMLFile::LoadFromStream() Error! \n");
+
+ return nResult;
+}
+
+int CXMLFile::LoadFromFile(LPCTSTR pszFileName)
+{
+ int nResult;
+ FILE* hFile = NULL;
+ DWORD dwFileSize, dwReadBytes;
+ LPBYTE pbBuffer = NULL;
+ LPTSTR pszXML = NULL;
+
+ hFile = fopen(pszFileName, "rb");
+
+ if (!hFile) {
+ nResult = -1;
+ goto finish;
+ }
+
+ fseek(hFile, 0, SEEK_END);
+ dwFileSize = ftell(hFile);
+ fseek(hFile, 0, SEEK_SET);
+
+ pbBuffer = new BYTE[ dwFileSize + 1 ];
+ IF_TRUE_GOTO( pbBuffer == NULL, TADC_MEMAlOC_ERROR );
+
+ dwReadBytes = fread ( pbBuffer, 1, dwFileSize + 1, hFile);
+
+ IF_TRUE_GOTO( dwFileSize != dwReadBytes, TADC_PARAMETER_ERROR );
+
+ pbBuffer[ dwFileSize ] = 0;
+
+ pszXML = new CHAR[ dwFileSize + 256 ];
+ IF_TRUE_GOTO( pszXML == NULL, TADC_MEMAlOC_ERROR );
+
+#ifdef _UNICODE
+ nResult = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)pbBuffer, -1, pszXML, dwFileSize + 256 );
+#else
+ memcpy(pszXML, pbBuffer, dwFileSize + 1);
+#endif
+
+ nResult = LoadFromStream(pszXML);
+
+ if (nResult)
+ goto finish;
+
+ nResult = 0;
+
+finish:
+ if (hFile)
+ fclose(hFile);
+
+ if (nResult)
+ DRM_TAPPS_EXCEPTION("CXMLFile::LoadFromFile() Error! \n");
+
+ if (pbBuffer)
+ delete []pbBuffer;
+
+ if (pszXML)
+ delete []pszXML;
+
+ return nResult;
+}
+
+int CXMLFile::_Parse()
+{
+ int nResult, i;
+ CXMLElement* pXMLElement = NULL;
+ CXMLElement* pCurrentElement = NULL;
+ CXMLElement* pTemp = NULL;
+ TCHAR szElementName[_MAX_NAME_LENGTH];
+ TCHAR szValue[_MAX_VALUE_LENGTH];
+ LPCTSTR psz;
+ size_t orig_pszXML_len = strlen(m_pszXML);
+ size_t tmp_pszXML_len = orig_pszXML_len;
+
+ _SKIP_WHITESPACE();
+
+ while (*m_pszXML != 0) {
+ _SKIP_WHITESPACE();
+
+ if (*m_pszXML == 0)
+ break;
+
+ if (*m_pszXML == '<') {
+ m_pszXML++;
+
+ _SKIP_WHITESPACE();
+
+ if (*m_pszXML == '!') {
+ //------------------------------------------------------------------------
+ //
+ // Comment
+ //
+ //------------------------------------------------------------------------
+ }
+ else if (*m_pszXML == '?') {
+ //------------------------------------------------------------------------
+ //
+ // <? ... ?>
+ //
+ //------------------------------------------------------------------------
+ psz = _tcsstr(m_pszXML, _T( "?>" ));
+ if (!psz) {
+ nResult = -1;
+ goto finish;
+ }
+
+ m_pszXML = psz + 2;
+ }
+ else if (*m_pszXML == '/') {
+ m_pszXML++;
+ //------------------------------------------------------------------------
+ //
+ // End Tag
+ //
+ //------------------------------------------------------------------------
+ nResult = _GetElementName((LPTSTR)szElementName);
+
+ if (nResult != 0)
+ goto finish;
+
+ //2011.04.27
+ if (!pCurrentElement) {
+ nResult = -1;
+ goto finish;
+ }
+
+ if (TADC_IF_StrCmp(pCurrentElement->GetName(), (LPTSTR)szElementName) != 0) {
+ nResult = -1;
+ goto finish;
+ }
+
+ tmp_pszXML_len = orig_pszXML_len;
+ while (*m_pszXML != '>' && tmp_pszXML_len > 0) {
+ tmp_pszXML_len--;
+ m_pszXML++;
+ }
+
+ m_pszXML++;
+
+ pTemp = _Pop();
+
+ if (pTemp)
+ pCurrentElement = pTemp;
+ else
+ pCurrentElement = m_pRoot;
+ }
+ else {
+ pXMLElement = new CXMLElement;
+ IF_TRUE_GOTO(pXMLElement == NULL, TADC_MEMAlOC_ERROR);
+
+ nResult = _GetElementName((LPTSTR)szElementName);
+ if (nResult)
+ goto finish;
+
+ pXMLElement->SetName((LPTSTR)szElementName);
+
+ if (!m_pRoot)
+ m_pRoot = pXMLElement;
+
+ if (pCurrentElement) {
+ pCurrentElement->AddChild(pXMLElement);
+ _Push(pCurrentElement);
+ }
+
+ pCurrentElement = pXMLElement;
+ }
+ }
+ else if (*m_pszXML == '/') {
+ m_pszXML++;
+
+ if (*m_pszXML != '>') {
+ nResult = -1;
+ goto finish;
+ }
+
+ pCurrentElement = _Pop();
+ }
+ else if (*m_pszXML == '>') {
+ m_pszXML++;
+ _SKIP_WHITESPACE();
+
+ i = 0;
+
+ tmp_pszXML_len = orig_pszXML_len;
+ while (*m_pszXML != '<' && tmp_pszXML_len > 0) {
+ tmp_pszXML_len--;
+ szValue[i] = *m_pszXML;
+ i++;
+ m_pszXML++;
+ }
+
+ szValue[i] = 0;
+ if (pCurrentElement)
+ pCurrentElement->SetValue((LPTSTR)szValue);
+ }
+ else {
+ _SKIP_WHITESPACE();
+
+ nResult = _GetAttributeNameAndValue((LPTSTR)szElementName, (LPTSTR)szValue);
+
+ if (nResult)
+ goto finish;
+
+ if (pCurrentElement)
+ pCurrentElement->AddAttribute((LPTSTR)szElementName, (LPTSTR)szValue);
+ }
+ }
+
+ nResult = 0;
+
+finish:
+ if (nResult)
+ DRM_TAPPS_EXCEPTION("CXMLFile::_Parse() Error!. nResult[%d]", nResult);
+
+ return nResult;
+}
+
+int CXMLFile::_GetElementName(LPTSTR pszElementName)
+{
+ _SKIP_WHITESPACE();
+
+ while ((*m_pszXML != 0 )
+ && (*m_pszXML != ' ')
+ && (*m_pszXML != '>')
+ && (*m_pszXML != '/')) {
+ *pszElementName = *m_pszXML;
+ m_pszXML++;
+ pszElementName++;
+ }
+
+ *pszElementName = 0;
+
+ return 0;
+}
+
+CXMLElement* CXMLFile::_Pop()
+{
+ if (m_nQueueIndex < 1)
+ return NULL;
+
+ return m_paElementQueue[--m_nQueueIndex];
+}
+
+int CXMLFile::_Push(IN CXMLElement* p)
+{
+ if (m_nQueueIndex >= (int)sizeof(m_paElementQueue) / (int)sizeof(m_paElementQueue[0]))
+ return ERROR_INSUFFICIENT_BUFFER;
+
+ m_paElementQueue[m_nQueueIndex++] = p;
+
+ return 0;
+}
+
+int CXMLFile::_GetAttributeNameAndValue(LPTSTR pszName, LPTSTR pszValue)
+{
+ int nResult, nLength, i;
+ LPCTSTR psz;
+ TCHAR chQuotation;
+ bool isFound;
+ LPTSTR origValueAddr = pszValue;
+ static T_ESCAPE_CHARSET stEscape[] = { { _T( "&amp" ), _T( '&' ) },
+ { _T( "&qt" ), _T( '>' ) },
+ { _T( "&lt" ), _T( '<' ) },
+ { _T( "&quot" ), _T( '"' ) },
+ { _T( "&apos" ), _T( '\'' ) } };
+
+ _SKIP_WHITESPACE();
+
+ psz = _tcschr( m_pszXML, '=' );
+ if (!psz) {
+ nResult = -1;//ERRORMSG( ERROR_SXS_XML_E_BADXMLDECL, NULL );
+ goto finish;
+ }
+
+ nLength = (int)(psz - m_pszXML);
+ if( _MAX_NAME_LENGTH < nLength + 1) {
+ nResult = -1;
+ goto finish;
+ }
+ memcpy(pszName, m_pszXML, nLength + 1);
+
+ m_pszXML = psz + 1;
+
+ _SKIP_WHITESPACE();
+
+ if (( *m_pszXML == '\'' ) || ( *m_pszXML == '"' )) {
+ chQuotation = *m_pszXML;
+ m_pszXML++;
+ }
+ else {
+ chQuotation = ' ';
+ }
+
+ while (*m_pszXML != 0 && ((pszValue - origValueAddr)< _MAX_VALUE_LENGTH) ) {
+ if (*m_pszXML == '&') {
+ isFound = FALSE;
+ for (i = 0; i < (int)sizeof(stEscape) / (int)sizeof(stEscape[0]); i++) {
+ if (TADC_IF_StrNCmp(m_pszXML, stEscape[i].pszEscape, TADC_IF_StrLen(stEscape[i].pszEscape)) == 0) {
+ *pszValue = stEscape[i].chReplace;
+ pszValue++;
+ m_pszXML += TADC_IF_StrLen(stEscape[i].pszEscape);
+ isFound = TRUE;
+
+ break;
+ }
+ }
+
+ if (isFound == FALSE) {
+ *pszValue = *m_pszXML;
+ pszValue++;
+ m_pszXML++;
+ }
+ }
+ else if (*m_pszXML == chQuotation) {
+ m_pszXML++;
+ break;
+ }
+ else if (*m_pszXML == '/' || *m_pszXML == '>')
+ {
+ if (chQuotation == ' ')
+ break;
+
+ *pszValue = *m_pszXML;
+ pszValue++;
+ m_pszXML++;
+ }
+ else
+ {
+ *pszValue = *m_pszXML;
+ pszValue++;
+ m_pszXML++;
+ }
+ }
+
+ *pszValue = 0;
+ nResult = 0;
+
+finish:
+ if (nResult)
+ DRM_TAPPS_EXCEPTION("CXMLFile::_GetAttributeNameAndValue() Error!");
+
+ return nResult;
+}
diff --git a/tadcore/include/CPointerArray.h b/tadcore/include/CPointerArray.h
new file mode 100644
index 0000000..a279382
--- /dev/null
+++ b/tadcore/include/CPointerArray.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 __CPOINTERARRAY_H__
+#define __CPOINTERARRAY_H__
+
+
+#if !defined(AFX_CPOINTERARRAY_H__AB67E4BE_A233_4E3E_B257_9830D90326EE__INCLUDED_)
+#define AFX_CPOINTERARRAY_H__AB67E4BE_A233_4E3E_B257_9830D90326EE__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "TadcTypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+class CPointerArray
+{
+protected:
+ LPVOID* m_ppData;
+ int m_nMaxSize;
+ int m_nNumOfData;
+
+public:
+ CPointerArray();
+ virtual ~CPointerArray();
+
+ int Add( LPVOID pData );
+ int Remove( int nIndex );
+ LPVOID Get( int nIndex );
+ inline int GetCount() { return m_nNumOfData; }
+ inline void RemoveAll() { m_nNumOfData = 0; }
+};
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // !defined(AFX_CPOINTERARRAY_H__AB67E4BE_A233_4E3E_B257_9830D90326EE__INCLUDED_)
+#endif /* __CPOINTERARRAY_H__ */
diff --git a/tadcore/include/CXMLAttribute.h b/tadcore/include/CXMLAttribute.h
new file mode 100644
index 0000000..1e68d4d
--- /dev/null
+++ b/tadcore/include/CXMLAttribute.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 "TadcTypes.h"
+
+#if !defined(AFX_CXMLATTRIBUTE_H__2B925786_3613_47B0_B85D_CAF2053F46DB__INCLUDED_)
+#define AFX_CXMLATTRIBUTE_H__2B925786_3613_47B0_B85D_CAF2053F46DB__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class CXMLAttribute
+{
+protected:
+ LPTSTR m_pszName;
+ LPTSTR m_pszValue;
+
+public:
+ CXMLAttribute();
+ virtual ~CXMLAttribute();
+
+ int SetName( LPCTSTR pszName );
+ int SetValue( LPCTSTR pszValue );
+
+ inline LPCTSTR GetName() { return m_pszName; }
+ inline LPCTSTR GetValue() { return m_pszValue; }
+};
+
+#endif // !defined(AFX_CXMLATTRIBUTE_H__2B925786_3613_47B0_B85D_CAF2053F46DB__INCLUDED_)
diff --git a/tadcore/include/CXMLElement.h b/tadcore/include/CXMLElement.h
new file mode 100644
index 0000000..d3f9c38
--- /dev/null
+++ b/tadcore/include/CXMLElement.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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.
+ */
+
+#if !defined(AFX_CXMLELEMENT_H__B6A6A39B_1980_4A4F_B68B_E87B53A3EE9B__INCLUDED_)
+#define AFX_CXMLELEMENT_H__B6A6A39B_1980_4A4F_B68B_E87B53A3EE9B__INCLUDED_
+
+#include "TadcTypes.h"
+#include "CXMLAttribute.h"
+#include "CPointerArray.h"
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class CXMLElement
+{
+protected:
+ LPTSTR m_pszName;
+ LPTSTR m_pszValue;
+
+ CPointerArray m_pChilds;
+ CPointerArray m_pAttributes;
+
+ int _SearchNodes( CPointerArray* ppaChildNodes, CXMLElement* pCurrent, LPCTSTR pszTagName, va_list args );
+
+public:
+ CXMLElement();
+ virtual ~CXMLElement();
+
+ int SetName( LPCTSTR pszName );
+ int SetValue( LPCTSTR pszValue );
+ int AddAttribute( LPCTSTR pszName, LPCTSTR pszValue );
+
+ inline LPCTSTR GetName() { return m_pszName; }
+ inline LPCTSTR GetValue() { return m_pszValue; }
+
+ int AddChild( CXMLElement* pChild );
+ LPCTSTR GetAttribute( LPCTSTR pszName );
+
+ inline int GetChildCount() { return m_pChilds.GetCount(); }
+ inline int GetAttributeCount() { return m_pAttributes.GetCount(); }
+ inline CXMLElement* GetChild( int nIndex ) { return (CXMLElement*)m_pChilds.Get( nIndex ); }
+ inline CXMLAttribute* GetAttribute( int nIndex ) { return (CXMLAttribute*)m_pAttributes.Get( nIndex ); }
+
+ int Find( CPointerArray* pSearchedChild, LPCTSTR pszChildName, ... );
+};
+
+#endif // !defined(AFX_CXMLELEMENT_H__B6A6A39B_1980_4A4F_B68B_E87B53A3EE9B__INCLUDED_)
diff --git a/tadcore/include/CXMLFile.h b/tadcore/include/CXMLFile.h
new file mode 100644
index 0000000..527162b
--- /dev/null
+++ b/tadcore/include/CXMLFile.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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.
+ */
+
+#if !defined(AFX_CXMLFILE_H__21F76587_B9C8_4407_9C16_186F3D47ADE1__INCLUDED_)
+#define AFX_CXMLFILE_H__21F76587_B9C8_4407_9C16_186F3D47ADE1__INCLUDED_
+
+#include "TadcTypes.h"
+#include "CXMLElement.h"
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#ifndef IN
+ #define IN
+#endif
+
+#ifndef OUT
+ #define OUT
+#endif
+
+#define ELEMENT_QUEUE_MAX 2048
+
+class CXMLFile
+{
+protected:
+ LPCTSTR m_pszXML;
+ CXMLElement* m_paElementQueue[ ELEMENT_QUEUE_MAX ];
+ int m_nQueueIndex;
+ CXMLElement* m_pRoot;
+
+ int _Parse();
+ int _GetElementName( LPTSTR pszElementName );
+ CXMLElement* _Pop();
+ int _Push( CXMLElement* p );
+ int _GetAttributeNameAndValue( LPTSTR pszName, LPTSTR pszValue );
+
+public:
+ CXMLFile();
+ virtual ~CXMLFile();
+
+ int LoadFromStream( LPCTSTR pszXML );
+ int LoadFromFile( LPCTSTR pszFileName );
+ inline CXMLElement* GetRoot() { return m_pRoot; }
+};
+
+#endif // !defined(AFX_CXMLFILE_H__21F76587_B9C8_4407_9C16_186F3D47ADE1__INCLUDED_)
diff --git a/tadcore/include/DUIDGenerator.h b/tadcore/include/DUIDGenerator.h
new file mode 100644
index 0000000..1327de4
--- /dev/null
+++ b/tadcore/include/DUIDGenerator.h
@@ -0,0 +1,29 @@
+//
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// 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 DUIDGenerator.h
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int get_duid(char **duid);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/tadcore/include/DrmFileApi.h b/tadcore/include/DrmFileApi.h
new file mode 100644
index 0000000..1d57060
--- /dev/null
+++ b/tadcore/include/DrmFileApi.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 __DRM_FILE_API_H__
+#define __DRM_FILE_API_H__
+
+
+#include "DrmFileMgr.h"
+#include "TADC_ErrorCode.h"
+
+/*
+enum
+{
+ DRM_SEEK_SET = 0,
+ DRM_SEET_CUR,
+ DRM_SEEK_END
+} DRM_SEEK_TYPE
+*/
+
+//typedef int DrmHandler;
+
+int DrmTdcFileOpen(const char* filePath, int mode, int* handle);
+
+int DrmTdcFileClose(int* handle);
+
+int DrmTdcFileRead(int* handle, void* pBuf, long long bufLen, long long* pReadLen);
+
+//int DrmTdcFileSeek(int* handle, DRM_SEEK_TYPE type, long long offset);
+
+int DrmTdcFileSeek(int* handle, long long offset, int origin);
+
+int DrmTdcFileTell(int* handle, long long *position);
+
+#endif
diff --git a/tadcore/include/DrmFileHandler.h b/tadcore/include/DrmFileHandler.h
new file mode 100644
index 0000000..7ef315b
--- /dev/null
+++ b/tadcore/include/DrmFileHandler.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 <stdio.h>
+
+#include "DrmTdcSvc.h"
+
+class DrmFileHandler
+{
+
+public:
+ DrmFileHandler(void);
+ ~DrmFileHandler(void);
+
+ int Construct(const char* szDrmFilePath);
+ int DrmSeek(long long offset, int origin);
+ long long DrmTell(void);
+ int DrmRead(void* pBuf, long long bufLen, long long* pReadLen);
+
+#ifndef TEST_CODE_ENABLED
+private:
+#endif
+ int DrmDecryptBlocks(void);
+ long long GetCurBlockIndex(void);
+
+ unsigned char *m_pFilePath;
+ unsigned char *m_pCID;
+ unsigned char *m_pCEK;
+ unsigned char *m_pDecBuf;
+
+ int m_PlaintextStartOffset;
+ FILE *m_pFP;
+
+ long m_encryptionLevel;
+ long long m_encryptionRange;
+ long long m_plaintextSize;
+ long long m_OriginEndOffset;
+ long long m_OriginCurOffset;
+ long long m_DrmCurOffset;
+ long long m_DrmEndOffset;
+ long long m_blockCnt;
+ long long m_curBlockIndex;
+ long long m_decReadlen;
+ long long m_extraReadlen;
+};
diff --git a/tadcore/include/DrmFileMgr.h b/tadcore/include/DrmFileMgr.h
new file mode 100644
index 0000000..d561efb
--- /dev/null
+++ b/tadcore/include/DrmFileMgr.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 <map>
+#include "DrmFileHandler.h"
+
+typedef std::map<int, DrmFileHandler *> DrmHandlerMap;
+
+class DrmFileMgr {
+public:
+ static DrmFileMgr *GetInstance();
+ static void FreeInstance(void);
+
+ int OpenFileHandler(const char *filePath, int mode, int *key);
+ int CloseFileHandler(int key);
+ int GetFileHandler(int key, DrmFileHandler **handler);
+
+private:
+ DrmFileMgr(void);
+ virtual ~DrmFileMgr(void);
+
+ void Construct(void);
+
+ static DrmFileMgr *m_pInstance;
+ DrmHandlerMap m_HandlerMap;
+};
diff --git a/tadcore/include/DrmTdcSvc.h b/tadcore/include/DrmTdcSvc.h
new file mode 100644
index 0000000..e105fb3
--- /dev/null
+++ b/tadcore/include/DrmTdcSvc.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 DrmTdcSvc.h
+ * @brief This file includes definitions of the Tizen Apps DRM functions.
+ * @author Sunggun.jung (sunggun.jung@samsung.com)
+ */
+
+#ifndef DRMTDCSVC_H
+#define DRMTDCSVC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "TADC_Core.h"
+
+
+//TDC DRM File Header Info
+typedef struct
+{
+ char cid[1024]; // CID ( Content ID )
+ char riurl[1024]; // RIURL ( Rights Issuer URL )
+
+} DrmTdcFileHeader;
+
+#ifndef IN
+#define IN
+#endif
+
+#ifndef OUT
+#define OUT
+#endif
+
+/**
+ * An application can get file Header Info ( CID, License URL )
+ *
+ * @param[in] filePath file path of Tizen Apps DRM contents
+ * @param[out] pFileHeader Pointer to be stored TAD Header information.
+ * @return This function returns TRUE on success or FALSE on failure.
+ * @remarks
+ * @see
+ * @since
+ */
+bool DrmTdcGetFileHeader
+(
+ IN const char *pTADCFilepath, //TDC DRM File Path
+ IN OUT DrmTdcFileHeader *pFileHeader //File Header Info ( CID, License URL )
+);
+
+/**
+ * An application can request purchase request for getting License.
+ *
+ * @param[in] pTADCFilepath File path of Tizen Apps DRM contents
+ * @param[out] pReqBuf Purchase Request Data
+ * @param[in][out] pReqBufLen IN : pReqBuf Length, OUT : Purchase Request Data String Size ( including null terminator )
+ * @param[out] pLicenseUrl License Acquisition URL Data
+ * @param[in][out] pLicenseUrlLen IN : pLicenseUrl Length, OUT : License Server URL Data String Size ( including null terminator )
+ * @return This function returns TRUE on success or FALSE on failure.
+ * @remarks
+ * @see DrmTdcGenerateLicenseRequest
+ * @since
+ */
+bool DrmTdcGeneratePurchaseRequest
+(
+ IN const char *pTADCFilepath, //TDC DRM File Path
+ IN OUT char *pReqBuf, //Purchase Request Data
+ IN OUT unsigned int *pReqBufLen, //IN : pReqBuf Length, OUT : Purchase Request Data String Size ( including null terminator )
+ IN OUT char *pLicenseUrl, //License Acquisition URL Data
+ IN OUT unsigned int *pLicenseUrlLen //IN : pLicenseUrl Length, OUT : License Server URL Data String Size ( including null terminator )
+);
+
+/**
+ * An application can request generate request for getting License.
+ *
+ * @param[in] pRespBuf Response Data String of the Purchase Request ( Null terminator string )
+ * @param[in] respBufLen pResBuf Length
+ * @param[in][out] pReqBuf License Request Data
+ * @param[in][out] pReqBufLen IN : pReqBuf Length, OUT : Rights Request Data String Size ( including null terminator )
+ * @param[in][out] pLicenseUrl License Acquisition URL Data
+ * @param[in][out] pLicenseUrlLen IN : IN : pLicenseUrl Length, OUT : Rights Issuer Server URL Data String Size ( including null terminator )
+ * @return This function returns TRUE on success or FALSE on failure.
+ * @remarks
+ * @see DrmTdcGeneratePurchaseRequest
+ * @since
+ */
+int DrmTdcGenerateLicenseRequest
+(
+ IN const char *pRespBuf, //Response Data String of the Purchase Request ( Null terminator string )
+ IN unsigned int respBufLen, //pResBuf Length
+ IN OUT char *pReqBuf, //License Request Data
+ IN OUT unsigned int *pReqBufLen, //IN : pReqBuf Length, OUT : Rights Request Data String Size ( including null terminator )
+ IN OUT char *pLicenseUrl, //License Acquisition URL Data
+ IN OUT unsigned int *pLicenseUrlLen //IN : pLicenseUrl Length, OUT : Rights Issuer Server URL Data String Size ( including null terminator )
+);
+
+/**
+ * An application can get TAD license which is encrypted.
+ *
+ * @param[in] pRespBuf Response Data String of the Rights Request ( Null terminator string )
+ * @param[in] respBufLen pResBuf Length
+ * @param[in][out] pDecLicenseBuf Decrypted Rights Object
+ * @param[in][out] decLicenseBufLen IN : pDecLicenseBuf Length, OUT : Decrypted Rights Object String Size ( including null terminator )
+ * @return This function returns TRUE on success or FALSE on failure.
+ * @remarks
+ * @see DrmTdcDecryptPackage
+ * @since
+ */
+int DrmTdcDecryptLicense
+(
+ IN const char *pRespBuf, //Response Data String of the Rights Request ( Null terminator string )
+ IN unsigned int respBufLen, //pResBuf Length
+ IN OUT char *pDecLicenseBuf, //Decrypted Rights Object
+ IN OUT unsigned int *decLicenseBufLen //IN : pDecLicenseBuf Length, OUT : Decrypted Rights Object String Size ( including null terminator )
+);
+
+/**
+ * An application can get decrypted contents(Apps) which is encrypted.
+ *
+ * @param[in] pTADCFilepath TDC DRM File Path
+ * @param[in] pLicenseBuf pResBuf Length
+ * @param[in] licenseBufLen pDecLicenseBuf Length
+ * @param[in] pDecryptedFile Decrypted File Path
+ * @return This function returns TRUE on success or FALSE on failure.
+ * @remarks
+ * @see DrmTdcDecryptLicense
+ * @since
+ */
+//Decrypt DRM File
+bool DrmTdcDecryptPackage
+(
+ IN const char *pTADCFilepath, //TDC DRM File Path
+ IN const char *pLicenseBuf, //Decrypted Rights Object
+ IN unsigned int licenseBufLen, //pDecLicenseBuf Length
+ IN const char *pDecryptedFile //Decrypted File Path
+);
+
+/**
+ * An application can get decrypted contents(Apps) which is encrypted.
+ *
+ * @param[in] pTADCFilepath TDC DRM File Path
+ * @param[in] t_RO Decrypted RO Info
+ * @param[in] pDecryptedFile Decrypted File Path
+ * @return This function returns TRUE on success or FALSE on failure.
+ * @remarks
+ * @see DrmTdcDecryptLicense
+ * @since
+ */
+//Decrypt DRM File
+bool DrmTdcDecryptPackage2
+(
+ IN const char *pTADCFilepath, //TDC DRM File Path
+ IN T_RO t_RO, //RO Info
+ IN const char *pDecryptedFile //Decrypted File Path
+);
+
+/**
+ * An application can check contents(Apps) which is valid.
+ *
+ * @param[in] szCid CID ( Content ID )
+ * @see DrmTdcGetFileHeader
+ * @since
+ */
+//Decrypt DRM File
+bool DrmTdcHasValidLicense
+(
+ IN const char *szCid // CID ( Content ID )
+);
+
+//DrmTdcDHInfo Structure Init
+void DrmTdcDHInfoInit(void);
+
+//DrmTdcDHInfo Structure Free
+bool DrmTdcDHInfoFree(int idx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tadcore/include/TADC_Core.h b/tadcore/include/TADC_Core.h
new file mode 100644
index 0000000..5df7b73
--- /dev/null
+++ b/tadcore/include/TADC_Core.h
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+
+#include "CPointerArray.h"
+#include "CXMLAttribute.h"
+#include "CXMLElement.h"
+#include "CXMLFile.h"
+
+#define STACKTRACE(pszFunction) // RETAILMSG(1, pszFunction);
+#undef ERRORMSG
+#define ERRORMSG //-1
+#define IF_ERROR_RETURN( error , errcode) if(error < 0){DRM_TAPPS_EXCEPTION("TADC Debug Error Code = %x", errcode); return error;}
+#define IF_TRUE_RETURN( error , errcode) if(error){DRM_TAPPS_EXCEPTION("TADC Debug Error Code = %x", errcode); return -1;}
+
+//2011.03.08
+#define IF_TRUE_RETURN2( error , do1, do2, do3, errcode) if(error){ do1; do2; do3; DRM_TAPPS_EXCEPTION("TADC Debug Error Code = %x", errcode); return -1;}
+
+#ifndef TADC_SWAP32
+#define TADC_SWAP32(x) ((((TADC_U32)(x) & 0x000000ffL) << 24) | (((TADC_U32)(x) & 0x0000ff00L) << 8) | (((TADC_U32)(x) & 0x00ff0000L) >> 8) | (((TADC_U32)(x) & 0xff000000L) >> 24))
+#endif
+
+#define TADC_U8 unsigned char
+#define TADC_U16 unsigned short
+#define TADC_U32 unsigned long
+#define DWORD unsigned long
+#define LPBYTE unsigned char*
+#define TCHAR unsigned char
+
+#define BYTE unsigned char
+#define UINT unsigned int
+#define ULONG unsigned long
+#define INT32 long
+#define INT64 long long
+#define TRUE 1
+#define FALSE 0
+
+
+#define REQU_MAXSIZE 1024*5 //2011.03.08 (HTTP Request Buffer Max Size)
+#define RESP_MAXSIZE 1024*10 //2011.03.08 (HTTP Response Buffer Max Size)
+
+#define ROXML_MAXSIZE 4096*2 //2011.03.08
+#define CERT_MAXSIZE 4096 //2011.03.08
+
+#define SID_SIZE 4
+#define CID_SIZE 1024 //2011.03.08 ( 32 -> 1024 )
+#define CEK_SIZE 32 // multiplication of 8
+#define GMT_SIZE 21
+
+// Core Value Size define
+#define DUID_SIZE 32
+#define DEVICEKEY_SIZE 16
+#define ROID_SIZE 32
+#define DHKey_SIZE 128 //Max 1024 bit
+
+// DRM Type : Tizen DRM DRM - 1
+#define TIZEN_DRM 1
+
+// RO Permission Type
+#define DUID_RULE 1
+
+typedef char CHAR;
+typedef bool BOOL;
+
+typedef struct t_file_header
+{
+ unsigned char Version[2];
+ unsigned char DRMType;
+ unsigned char ContentsType[128];
+ long long TotalSize;
+ long long Offset1;
+ long long Offset2;
+ long long Offset3;
+ long long Offset4;
+ long long Offset5;
+ long long Offset6;
+ long long Offset7;
+ long long Offset8;
+}T_FILE_HEADER;
+
+typedef struct t_drm_header
+{
+ long XmlSize;
+ unsigned char Version[2];
+ unsigned char *SID;
+ unsigned char *CID;
+ unsigned char ContentsType[128];
+ long EncryptionMethod;
+ long EncryptionLevel;
+ long long EncryptionRange;
+ unsigned char *RIURL;
+ long long PlaintextSize;
+ unsigned char *Packdate;
+ unsigned char *CEK;
+} T_DRM_HEADER;
+
+typedef struct t_decice_info
+{
+ unsigned char DUID[DUID_SIZE + 1];
+} T_DEVICE_INFO;
+
+typedef struct t_dh_info
+{
+ unsigned char p[DHKey_SIZE+1]; // DH prime binary
+ long pSize;
+ long g; // DH primitive root. ( 2 or 5 )
+ unsigned char a[DHKey_SIZE+1]; // DH Client private binary
+ long aSize;
+ unsigned char A[DHKey_SIZE+1]; // DH Client public binary (ga mod p)
+ long ASize;
+ unsigned char B[DHKey_SIZE+1]; // DH Server public binary (gb mod p)
+ long BSize;
+ unsigned char K[32+1]; // DH Session Key
+} T_DH_INFO;
+
+typedef struct t_ro_content
+{
+ unsigned char *CID;
+ unsigned char *CEK;
+} T_RO_CONTENT;
+
+typedef struct t_roacq_info
+{
+ unsigned char* ROAcqURL;
+ unsigned char* ReqID;
+ T_DH_INFO t_DHInfo;
+ unsigned char sTimeStamp[21];
+} T_ROACQ_INFO;
+
+typedef struct t_individual
+{
+ unsigned char BindingType;
+ unsigned char* DUID;
+} T_INDIVIDUAL;
+
+typedef struct t_ro_permission
+{
+ T_INDIVIDUAL t_Individual;
+} T_RO_PERMISSION;
+
+
+typedef struct t_ro
+{
+ short int PerFlag;
+ T_RO_CONTENT t_Content;
+ T_RO_PERMISSION t_Permission;
+} T_RO;
+
+int TADC_SetDeviceInfo(T_DEVICE_INFO *t_DeviceInfo);
+int TADC_GetFileHeader(unsigned char *inBuffer, T_FILE_HEADER *t_FileHeader);
+int TADC_GetDRMHeader(unsigned char *inBuffer, T_DRM_HEADER *t_DRMHeader);
+int TADC_GetDRMHeaderInfo(unsigned char * inBuffer, T_DRM_HEADER *t_DRMHeader);
+int TADC_GetDRMHeaderFromFile(const char *pTADCFilepath, T_FILE_HEADER *t_FileHeader, T_DRM_HEADER *t_DRMHeader);
+int TADC_MakeRequestLicense(T_DEVICE_INFO *t_DeviceInfo, T_FILE_HEADER *t_FileHeader, T_DRM_HEADER *t_DRMHeader, unsigned char * outBuffer, size_t outBufferSize);
+int TADC_GetROAcqInfo(unsigned char *inBuffer, T_ROACQ_INFO *t_ROAcqInfo);
+int TADC_MakeRequestRO(T_ROACQ_INFO *t_ROAcqInfo, unsigned char *outBuffer, size_t outBufferSize, unsigned char *ROVer=NULL); //2011.03.08
+int TADC_GetResponseRO(unsigned char *inBuffer, T_ROACQ_INFO *t_ROAcqInfo, T_RO *t_RO, unsigned char *outBuffer);
+int TADC_GetResponseROInfo(LPBYTE pszXML, T_RO *t_RO);
+int TADC_GetHashReqID(unsigned char *inBuffer, unsigned char *hashReqID);
+int TADC_GetCEK(T_DEVICE_INFO *t_DeviceInfo, T_RO *t_RODB, T_DRM_HEADER *t_DRMHeader );
+int TADC_DecryptBlock(char* pbBuffer, int nSize, T_DRM_HEADER *t_DRMHeader);
+int TADC_VerifyROSignature(IN LPBYTE pszXML);
+DWORD TADC_GetLastError(void);
+int TADC_MEMFree_RO(T_RO *t_ro);
+int TADC_MEMFree_FileHeader(T_FILE_HEADER *t_FileHeader);
+int TADC_MEMFree_DRMHeader(T_DRM_HEADER *t_DrmHeader);
+int TADC_MEMFree_ROAcqInfo(T_ROACQ_INFO *t_ROAcqInfo);
diff --git a/tadcore/include/TADC_ErrorCode.h b/tadcore/include/TADC_ErrorCode.h
new file mode 100644
index 0000000..e7515df
--- /dev/null
+++ b/tadcore/include/TADC_ErrorCode.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 __TADC_ERRORCODE_H__
+#define __TADC_ERRORCODE_H__
+
+#include "drm-tizen-error.h"
+
+#endif // __TADC_ERRORCODE_H__
+
diff --git a/tadcore/include/TADC_IF.h b/tadcore/include/TADC_IF.h
new file mode 100644
index 0000000..f492f30
--- /dev/null
+++ b/tadcore/include/TADC_IF.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <stdbool.h>
+
+#include "TADC_Sub.h"
+#include "drm-tizen-mid.h"
+
+#define RO_ISSUER_ROOT_CERTS_DIR ISSUER_ROOT_CERTS_DIR
+
+int TADC_IF_GetDUID(char *DUID);
+
+int TADC_IF_GetDHKey(T_DH_INFO *t_dhinfo);
+int TADC_IF_GetDHKey_K(T_DH_INFO *t_dhinfo);
+
+int TADC_IF_AES_CTR(int keyLen, unsigned char *pKey, int ivLen, unsigned char *pIV, int inLen, unsigned char *in, int *pOutLen, unsigned char *out);
+int TADC_IF_SHA1(unsigned char *in, int inLen, unsigned char *out);
+
+size_t TADC_IF_StrLen(const char *string);
+int TADC_IF_StrCmp(const char *string1, const char *string2);
+int TADC_IF_StrNCmp(const char *string1, const char *string2, size_t count);
+char *TADC_IF_StrNCpy(char *strDestination, const char *strSource, size_t count);
+
+int TADC_IF_MemCmp(const void *buf1, const void *buf2, size_t count);
+void TADC_IF_MemCpy(void *dest, const void *src, size_t count);
+void TADC_IF_MemSet(void *dest, int c, size_t count);
+
+void *TADC_IF_Malloc(size_t size);
+void TADC_IF_Free(void *memblock);
+
+int TADC_IF_AtoI(char *str);
+
+void TADC_IF_Debug(const char *str);
+
+int TADC_IF_VerifySignature( unsigned char* inData, int inLen,
+ unsigned char* sigData, int sigLen,
+ unsigned char* cert, int certLen );
+
+int TADC_IF_VerifyCertChain( unsigned char* rica, int ricaLen,
+ unsigned char* cert, int certLen );
diff --git a/tadcore/include/TADC_Sub.h b/tadcore/include/TADC_Sub.h
new file mode 100644
index 0000000..7a4e11d
--- /dev/null
+++ b/tadcore/include/TADC_Sub.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "TADC_Core.h"
+
+extern DWORD m_NEDErrorCode;
+
+extern UINT htons_(UINT hostshort);
+extern DWORD htonl_(DWORD hostlong);
+extern INT64 _hton64( INT64 n64host );
diff --git a/tadcore/include/TADC_Util.h b/tadcore/include/TADC_Util.h
new file mode 100644
index 0000000..4ac466f
--- /dev/null
+++ b/tadcore/include/TADC_Util.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "TadcTypes.h"
+
+LPSTR Base64Encode( LPBYTE pbData, int nLength ) ;
+LPBYTE Base64Decode( LPCSTR pszString, int* pnLength ) ;
+int FindString( unsigned char *in, int inLen, unsigned char *find, int findLen );
+int HEX2BIN( LPCSTR pszHex, LPBYTE baBin, int* pnLength ) ;
diff --git a/tadcore/include/TadcTypes.h b/tadcore/include/TadcTypes.h
new file mode 100644
index 0000000..5834858
--- /dev/null
+++ b/tadcore/include/TadcTypes.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 TadcTypes.h
+ * @brief This file includes definitions of constants,
+ * enumerations, and datastructures for the DRM service.
+ * @version 1.0
+ */
+
+#ifndef __TADC_DRM_TYPES_H__
+#define __TADC_DRM_TYPES_H__
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#define _T
+#define IF_ERROR_GOTO( error ) if( FAILED( HRESULT_FROM_WIN32( error ) ) ) { nResult = ERRORMSG( error, NULL ); goto finish; }
+#define IF_TRUE_GOTO( cond, error ) if( cond ) { nResult = -1; goto finish; }
+
+#ifndef _SHP_SIMUL
+typedef void* LPVOID;
+typedef const char* LPCTSTR;
+typedef unsigned char* LPBYTE;
+typedef char TCHAR;
+typedef char* LPTSTR;
+typedef LPTSTR LPSTR;
+typedef LPCTSTR LPCTSTR;
+typedef LPCTSTR LPCSTR;
+
+//typedef HFile HANDLE;
+#define ERROR_INVALID_DATA 13L
+#define ERROR_INSUFFICIENT_BUFFER 122L // dderror
+//#define CopyMemory AcMemcpy
+#define INVALID_HOBJ NULL
+#endif
+
+#endif //__TADC_DRM_TYPES_H__
diff --git a/tappsd/inc/DTapps2Base64.h b/tappsd/inc/DTapps2Base64.h
new file mode 100644
index 0000000..2741427
--- /dev/null
+++ b/tappsd/inc/DTapps2Base64.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 DTapps2Base64.h
+ * @brief This file includes declarations for Base64 Encode Decode APIs.
+ */
+
+#ifndef __DTAPPS_BASE64_H__
+#define __DTAPPS_BASE64_H__
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "drm_intf_tapps.h"
+
+BOOL DTappsB64Encode(unsigned char* in, int in_size, unsigned char* out, int out_size);
+int DTappsB64Decode(unsigned char* in, int in_size, unsigned char* out, int& out_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /*__DTAPPS_BASE64_H__ */
diff --git a/tappsd/inc/DTapps2HMAC.h b/tappsd/inc/DTapps2HMAC.h
new file mode 100644
index 0000000..3cac56b
--- /dev/null
+++ b/tappsd/inc/DTapps2HMAC.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 DTapps2HMAC.h
+ * @brief This file includes declarations relating to HMAC.
+ */
+
+#ifndef __DTAPPS_HMAC_H__
+#define __DTAPPS_HMAC_H__
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "drm_intf_tapps.h"
+
+void DTappsCalHMACSHA1(unsigned char* key,int key_len,unsigned char* msg,size_t msglen,unsigned char *md,unsigned int *md_len);
+int DTappsGetDeviceKey(unsigned char **pDevKey,unsigned int *DevKeyLen);
+void DTappsFreeDeviceKey(unsigned char **pDevKey);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__DTAPPS_HMAC_H__ */
diff --git a/tappsd/inc/DTapps2Rights.h b/tappsd/inc/DTapps2Rights.h
new file mode 100644
index 0000000..66a8e71
--- /dev/null
+++ b/tappsd/inc/DTapps2Rights.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 DTapps2Rights.h
+ * @brief This file includes declarations and classes relating to Rights.
+ */
+
+#ifndef __DTAPPS_RIGHTS_H__
+#define __DTAPPS_RIGHTS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "drm_intf_tapps.h"
+
+#define DTAPPS_NAME_SIZE 512
+#define DTAPPS_CEK_SIZE 32
+#define DTAPPS_CID_SIZE 1024
+
+typedef enum
+{
+ DTAPPS_INSTALL,
+ DTAPPS_VERIFY,
+} DTAPPS_OPERATION;
+
+typedef struct
+{
+ unsigned char DUID[DTAPPS_DUID_SIZE + 1];
+} DTAPPS_CONSTRAINTS;
+
+/*
+typedef enum
+{
+ DTAPPS_LIC_VALID = 1,
+ DTAPPS_LIC_NO_LICENCE,
+ DTAPPS_LIC_DUID_MISMATCH,
+ DTAPPS_LIC_UNKNOWN_ERROR = -1,
+ DTAPPS_LIC_DB_ERROR = -998,
+} int;
+*/
+
+typedef struct
+{
+ int r_id;
+ char name[512];
+ char cid[1024];
+ char time[64];// enough size
+ #ifdef DTAPPS_STORE_CEK_IN_DB
+ char cek[128];
+ char cek_hash[64];
+ #endif
+ char constraint_buffer[512];
+ char constraint_hash[64];
+} DTAPPS_RIGHTS_ROW;
+
+int DTappsValidateConstraints(DTAPPS_CONSTRAINTS* st_const, DTAPPS_OPERATION opr);
+int DTappsInstallLicense(const char* declicbuffer);
+int DTappsHasValidLicense(const char* szCid);
+int DTappsGetROInfo(const char* pszXML, T_RO *t_RO, unsigned char* name);
+int DTappsCalcEval(DTAPPS_CONSTRAINTS* st_const);
+BOOL DTappsGetCEK(const char* szCid,T_RO* t_RO);
+
+/* Declaration for Table Handling */
+BOOL DTapps_RIGHTS_INSTALL(const char* name,
+ const char* time,
+ #ifdef DTAPPS_STORE_CEK_IN_DB
+ const char* cek,
+ const char* cek_hash,
+ #endif
+ const char* constraint_buffer,
+ const char* constraint_hash,
+ const char* cid,
+ BOOL isUpdate);
+
+BOOL DTapps_RIGHTS_SELECT_ONE(const char* cid, DTAPPS_RIGHTS_ROW* row);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__DTAPPS_RIGHTS_H__ */
diff --git a/tappsd/inc/DTapps2SqliteDB.h b/tappsd/inc/DTapps2SqliteDB.h
new file mode 100644
index 0000000..4e434d9
--- /dev/null
+++ b/tappsd/inc/DTapps2SqliteDB.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 DTapps2SqliteDB.h
+ * @brief This file includes declarations and classes relating to DataBase.
+ */
+
+#ifndef __DTAPPS_SQLITE_DB_H__
+#define __DTAPPS_SQLITE_DB_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "TADC_Core.h"
+#include "drm_intf_tapps.h"
+
+#define DTAPPS_SQL_FREE_TABLE sqlite3_free_table
+
+typedef struct _tagTAPPSSqliteSelectTable{
+ sqlite3* handle;
+ char** result;
+ int n_rows;
+ int n_cols;
+}TAPPSSqliteSelectTable;
+
+/* Declarations for DB Wrappers */
+BOOL DTappsDBOpen(void *&pDb,const char* CallingFun);
+BOOL DTappsDBGet(void *& pDBConnection);
+BOOL DTappsDBClose(const char* CallingFun);
+BOOL DTappsDBBeginImmedTrans (const char* CallingFun);
+BOOL DTappsDBCommit(const char* CallingFun);
+BOOL DTappsDBRollback (const char* CallingFun);
+BOOL DTappsExecuteSQL(void* pDB, const char* query);
+BOOL DTappsSQLGetTable(void* pDB, const char* query, TAPPSSqliteSelectTable* select_table);
+char* DTappsGetSQLCreateTable(const char* tableName);
+void* DTappsStmtPrepare(void* pDB, const char* query);
+int DTappsStmtBindParam (
+ void* pStmt,
+ unsigned int dIdx,
+ unsigned int Type,
+ void* pParam,
+ unsigned int dParamSize );
+int DTappsStmtExecute (void* pStmt);
+int DTappsStmtRelease (void* pStmt);
+BOOL DTapps_DB_Install(const char* sql_query);
+BOOL DTapps_Read_DB(const char* sql_query, TAPPSSqliteSelectTable* select_table);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__DTAPPS_SQLITE_DB_H__ */
diff --git a/tappsd/inc/DTapps2Time.h b/tappsd/inc/DTapps2Time.h
new file mode 100644
index 0000000..4a3ec33
--- /dev/null
+++ b/tappsd/inc/DTapps2Time.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 DTapps2Time.h
+ * @brief This file includes declarations relating to TIME APIs.
+ */
+
+#ifndef __DTAPPS_TIME_H__
+#define __DTAPPS_TIME_H__
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "drm_intf_tapps.h"
+
+BOOL DTappsDtTmStr2Sec(unsigned char *time_str,time_t *TotalSec);
+BOOL DTappsDtTmStr2StrucTm(unsigned char *time_str,struct tm *time_fmt);
+BOOL DTappsGetSecureTime(time_t* seconds);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__DTAPPS_TIME_H__ */
diff --git a/tappsd/inc/drm_intf_tapps.h b/tappsd/inc/drm_intf_tapps.h
new file mode 100644
index 0000000..e86df0c
--- /dev/null
+++ b/tappsd/inc/drm_intf_tapps.h
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 drm_intf_tapps.h
+ * @brief This file includes declarations of the drm TAPPS intf APIs.
+ */
+
+#ifndef __DRM_INTF_TAPPS_H__
+#define __DRM_INTF_TAPPS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <linux/unistd.h>
+#include <unistd.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <ctype.h>
+#include <stdint.h>
+#include <dirent.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <glib.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+
+#include "db-util.h"
+
+#include "drm-tizen-mid.h"
+#include <openssl/aes.h>
+
+/* Enable this flag during development time */
+#define _TAPPS_DEBUG_ENABLE_
+
+/* IMEI and other VCONF Paths */
+
+#define DTAPPS_DUID_SIZE 32
+
+#if 0
+#define DTAPPS_IMEI_PATH VCONFKEY_TELEPHONY_IMEI
+#endif
+
+/*************************************************************************************************************/
+typedef bool BOOL;
+
+/* Constants */
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/*************************************************************************************************************/
+/* DB Details */
+
+/* drm db schema name */
+#define DTAPPS_DB_NAME DB_PATH
+
+typedef enum {
+ TAPPSDB_TYPE_NONE,
+ TAPPSDB_TYPE_INT,
+ TAPPSDB_TYPE_DATETIME,
+ TAPPSDB_TYPE_CHAR,
+ TAPPSDB_TYPE_VARCHAR,
+ TAPPSDB_TYPE_BINARY,
+ TAPPSDB_TYPE_BLOB,
+ TAPPSDB_TYPE_UNKNOWN = 0xFFFFFFFF
+} TAPPSDbType;
+
+/* Enable this Flag if CEK is to be stored in DB */
+#define DTAPPS_STORE_CEK_IN_DB
+
+/*************************************************************************************************************/
+
+/* Logs and Macros */
+
+#define MID_DRM 200
+#define MID_EXCEPTION 100
+
+#define MCATCH_B _M_catch:
+
+#define MTHROW_B \
+{ \
+ goto _M_catch; \
+}
+
+#define MTHROW_BL \
+{ \
+ M_LOGLINE("Throw error") \
+ goto _M_catch; \
+}
+
+
+#define MCFG_DISPLAY_ERROR_LINE
+
+#define DRM_LINUX_SYSDEBUG(dbg_lvl, FMT, ARG...) \
+{ \
+ if ((dbg_lvl) == MID_EXCEPTION) \
+ DRM_TAPPS_EXCEPTION(FMT, ##ARG); \
+ else if((dbg_lvl) == MID_DRM) \
+ DRM_TAPPS_LOG(FMT, ##ARG); \
+ else \
+ DRM_TAPPS_FRQ_LOG(FMT, ##ARG); \
+}
+
+#ifdef MCFG_DISPLAY_ERROR_LINE
+#define M_LOGLINE(log_prefix) DRM_LINUX_SYSDEBUG(MID_EXCEPTION, "(%s)[Statement] "#log_prefix"", __func__)
+#else
+#define M_LOGLINE(log_prefix)
+#endif // MCFG_DISPLAY_ERROR_LINE
+
+#define MTRY_BL(f) \
+{ \
+ if ((f) == 0) { \
+ M_LOGLINE("Try catched("#f")") \
+ goto _M_catch; \
+ } \
+}
+
+/*************************************************************************************************************/
+
+/* New and Delete */
+
+#include <new>
+#define NEW new (std::nothrow)
+
+#define MDELETE(x) \
+{ \
+ if (x) { \
+ delete x; \
+ x=0; \
+ } \
+}
+
+#define MDELETES(x) \
+{ \
+ if (x) { \
+ delete [] x; \
+ x=0; \
+ } \
+}
+
+#define MDELETE0 MDELETE
+
+#define MDELETES0 MDELETES
+
+/*************************************************************************************************************/
+/* Mutex structure */
+typedef pthread_mutex_t dtapps_mutex_t;
+
+#define dtappslockarg dtapps_mutex_t*
+
+int dtapps_mutex_lock (dtappslockarg dtapps_mutex);
+int dtapps_mutex_unlock (dtappslockarg dtapps_mutex);
+
+/*************************************************************************************************************/
+/* Memory Operations Wrapper APIs */
+
+#define DTAPPS_MEMSET memset
+#define DTAPPS_MEMCPY memcpy
+#define DTAPPS_MALLOC malloc
+#define DTAPPS_MEMCPY memcpy
+#define DTAPPS_MEMCMP memcmp
+#define DTAPPS_FREE free
+
+/*************************************************************************************************************/
+
+/* Time Wrapper APIs */
+
+#define DTAPPS_TIME time
+#define DTAPPS_MKTIME mktime
+#define DTAPPS_GMTIME gmtime
+#define DTAPPS_GMTIME_THREAD_SAFE gmtime_r
+#define DTAPPS_ASCTIME asctime
+
+/* String Operations Wrapper APIs */
+#ifdef _TAPPS_DEBUG_ENABLE_
+unsigned int TAPPS_gstrlcat(char* s1,const char* s2,unsigned int destsize,const char* funName, unsigned int lineno);
+unsigned int TAPPS_gstrlcpy(char* s1,const char* s2,unsigned int destsize,const char* funName, unsigned int lineno);
+unsigned int TAPPS_strlen(const char* s,const char* funName, unsigned int lineno);
+
+#define TAPPS_GSTRLCPY(dest,src,LenDest) TAPPS_gstrlcpy(dest,src,LenDest,__func__,__LINE__)
+#define TAPPS_GSTRLCAT(dest,src,LenDest) TAPPS_gstrlcat(dest,src,LenDest,__func__,__LINE__)
+#define TAPPS_STRLEN(string) TAPPS_strlen(string,__func__,__LINE__)
+#else
+#define TAPPS_GSTRLCPY(dest,src,LenDest) g_strlcpy(dest, src, LenDest)
+#define TAPPS_GSTRLCAT(dest,src,LenDest) g_strlcat(dest, src, LenDest)
+#define TAPPS_STRLEN(string) strlen(string)
+#endif
+
+#define DTAPPS_SNPRINTF snprintf
+#define DTAPPS_ATOI atoi
+#define DTAPPS_STRNCMP strncmp
+
+int TAPPS_strnicmp(const char * s1, const char * s2, unsigned int sz);
+/*************************************************************************************************************/
+/* SLEEP API */
+
+void dtapps_sleep(unsigned int TimeInSec,unsigned int TimeInMicroSec);
+
+/*************************************************************************************************************/
+
+/*************************************************************************************************************/
+/* OPENSSL APIs */
+#define DTAPPS_AES_SET_ENCR_KEY AES_set_encrypt_key
+#define DTAPPS_AES_SET_DECR_KEY AES_set_decrypt_key
+#define DTAPPS_AES_WRAP_KEY AES_wrap_key
+#define DTAPPS_AES_UNWRAP_KEY AES_unwrap_key
+
+/*************************************************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DRM_INTF_TAPPS_H__ */
diff --git a/tappsd/src/db/DTapps2SqlData.cpp b/tappsd/src/db/DTapps2SqlData.cpp
new file mode 100644
index 0000000..475693f
--- /dev/null
+++ b/tappsd/src/db/DTapps2SqlData.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 DTapps2SqlData.cpp
+ * @brief This file contains all the Database tables.
+ */
+
+#include "drm_intf_tapps.h"
+
+#define DTAPPS_TABLE_NAME(name) name "\0"
+#define DTAPPS_TABLE_CONTINUE "\0\1"
+#define DTAPPS_TABLE_END "\0",
+
+const char* dtappsCreateTableSQLData[] =
+{
+ DTAPPS_TABLE_NAME("dtapps2rights")
+ "CREATE TABLE dtapps2rights ("
+ "r_id INTEGER PRIMARY KEY AUTOINCREMENT,"
+ "name VARCHAR(512) DEFAULT NULL,"
+ "cid VARCHAR(1024) DEFAULT NULL,"
+ "time_t DATETIME,"
+ #ifdef DTAPPS_STORE_CEK_IN_DB
+ "cek VARCHAR(128) DEFAULT NULL,"
+ "cek_hash VARCHAR(64) DEFAULT NULL,"
+ #endif
+ "constraint_buffer VARCHAR(512) DEFAULT NULL,"
+ "constraint_hash VARCHAR(64) DEFAULT NULL"
+ ");"
+
+ DTAPPS_TABLE_END
+ NULL// empty do not delete this line
+};
diff --git a/tappsd/src/db/DTapps2SqliteDB.cpp b/tappsd/src/db/DTapps2SqliteDB.cpp
new file mode 100644
index 0000000..4789f07
--- /dev/null
+++ b/tappsd/src/db/DTapps2SqliteDB.cpp
@@ -0,0 +1,958 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 DTapps2SqliteDB.cpp
+ * @brief This file includes functions relating to DataBase.
+ */
+
+#include "DTapps2SqliteDB.h"
+#include <map>
+
+/* Define EXPORT_API temporary */
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+static dtapps_mutex_t dtapps_sqlite_db_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+typedef long int dtappsThreadID;
+
+ class DtappsDBConnectionInfo
+ {
+ public:
+ DtappsDBConnectionInfo();
+ int countOpenConnection;
+ sqlite3 *pDBConnection;
+ };
+
+ using namespace std;
+ static std::map<dtappsThreadID, DtappsDBConnectionInfo *> g_dtapps_sqlite_connection_table;
+
+ DtappsDBConnectionInfo::DtappsDBConnectionInfo()
+ {
+ countOpenConnection=0;
+ pDBConnection=NULL;
+ }
+
+ class TAPPSDbApiLock
+ {
+ public:
+ TAPPSDbApiLock();
+ ~TAPPSDbApiLock();
+ };
+
+ TAPPSDbApiLock::TAPPSDbApiLock()
+ {
+ DRM_TAPPS_FRQ_LOG("LOCK by TID = %ld",drmgettid());
+ if (0 != dtapps_mutex_lock (&dtapps_sqlite_db_mutex))
+ {
+ DRM_TAPPS_EXCEPTION("Error while mutex locking.");
+ }
+ }
+
+ TAPPSDbApiLock::~TAPPSDbApiLock()
+ {
+ DRM_TAPPS_FRQ_LOG("UNLOCK by TID = %ld",drmgettid());
+ if (0 != dtapps_mutex_unlock(&dtapps_sqlite_db_mutex))
+ {
+ DRM_TAPPS_EXCEPTION("Error while mutex unlocking");
+ }
+ }
+
+#define __DTAPPS_DB_SQLITE_RETRY__ (10)
+
+#define DTAPPS_SQLITE3_SQL_BEGIN_IMMEDIATE "BEGIN IMMEDIATE TRANSACTION"
+#define DTAPPS_SQLITE3_SQL_COMMIT "COMMIT TRANSACTION"
+#define DTAPPS_SQLITE3_SQL_ROLLBACK "ROLLBACK TRANSACTION"
+
+/* DataBase Related API Wrappers */
+BOOL DTappsDBOpen(void *&pDb, const char* CallingFun)
+{
+ DRM_TAPPS_LOG("[%s]: started.Calling function = %s",__func__,CallingFun);
+
+ TAPPSDbApiLock Dblock;
+ dtappsThreadID id_curr_thread = drmgettid();
+
+ bool IsMemAllocated = false;
+ int result = SQLITE_ERROR;
+ unsigned int pairCount = 0;
+ sqlite3* h_db = NULL;
+ DtappsDBConnectionInfo *pDBConnectionInfo = NULL;
+
+ DRM_TAPPS_SECURE_LOG("DB-OPEN-CLOSE [%s]Parent Process ID=[%ld]:Process-ID=[%ld]:Thread-ID=[%ld], id_curr_thread=[%ld]",__func__,getppid(),getpid(),drmgettid(), id_curr_thread);
+
+ pairCount = g_dtapps_sqlite_connection_table.count(id_curr_thread);
+ DRM_TAPPS_FRQ_LOG("pairCount=[%u]", pairCount);
+
+ if (0 != pairCount)
+ {
+ DRM_TAPPS_FRQ_LOG("Connection already exists.. pairCount=[%ld]", pairCount);
+ pDBConnectionInfo = g_dtapps_sqlite_connection_table[id_curr_thread];
+ DRM_TAPPS_FRQ_LOG("pDBConnectionInfo=[0x%x]", pDBConnectionInfo);
+
+ MTRY_BL(NULL != pDBConnectionInfo);
+ MTRY_BL(NULL != pDBConnectionInfo->pDBConnection);
+ DRM_TAPPS_FRQ_LOG("pDBConnectionInfo->countOpenConnection=[%d], pDBConnectionInfo->pDBConnection=[0x%x]", pDBConnectionInfo->countOpenConnection, pDBConnectionInfo->pDBConnection);
+
+ ++(pDBConnectionInfo->countOpenConnection);
+ pDb = pDBConnectionInfo->pDBConnection;
+ }
+ else
+ {
+ DRM_TAPPS_LOG("no connection exists.. pairCount=[%ld]", pairCount);
+ pDBConnectionInfo = NEW DtappsDBConnectionInfo;
+ MTRY_BL(NULL != pDBConnectionInfo);
+ IsMemAllocated = true; // prevent fix
+
+ DRM_TAPPS_FRQ_LOG("Opening DB connection.");
+
+ result = db_util_open(DTAPPS_DB_NAME, &h_db, 0);
+ if (result != SQLITE_OK)
+ {
+ DRM_TAPPS_EXCEPTION("sqlite msg :[%d]%s",result, sqlite3_errmsg(h_db));
+ DRM_TAPPS_SECURE_LOG("db name :%s", DTAPPS_DB_NAME);
+ MTHROW_BL
+ }
+
+ DRM_TAPPS_FRQ_LOG("sqlite3_open() is success. h_db:%x", h_db);
+
+ pDBConnectionInfo->countOpenConnection = 1;
+ pDBConnectionInfo->pDBConnection = h_db; h_db = NULL;
+
+ pDb = pDBConnectionInfo->pDBConnection;
+
+ // Insert the node
+ DRM_TAPPS_FRQ_LOG("pDBConnectionInfo->countOpenConnection=[%d], pDBConnectionInfo->pDBConnection=[0x%x]", pDBConnectionInfo->countOpenConnection, pDBConnectionInfo->pDBConnection);
+
+ g_dtapps_sqlite_connection_table.insert(pair<dtappsThreadID, DtappsDBConnectionInfo *>(id_curr_thread, pDBConnectionInfo));pDBConnectionInfo = NULL;
+ }
+
+ DRM_TAPPS_LOG("This fn finishes successfully.");
+
+ return TRUE;
+
+MCATCH_B
+
+ if (true == IsMemAllocated)
+ {
+ MDELETE(pDBConnectionInfo);
+ }
+ DRM_TAPPS_EXCEPTION("This fn fails");
+
+ return FALSE;
+}
+
+BOOL DTappsDBGet(void *& pDBConnection)
+{
+ DRM_TAPPS_LOG("Inside %s", __func__);
+
+ TAPPSDbApiLock Dblock;
+ unsigned int pairCount;
+ dtappsThreadID id_curr_thread = drmgettid();
+ pDBConnection = NULL;
+
+ DRM_TAPPS_LOG("Parent Process ID=[%ld]:Process-ID=[%ld]:Thread-ID=[%ld], id_curr_thread=[%ld]",getppid(),getpid(),drmgettid(), id_curr_thread);
+
+ pairCount = g_dtapps_sqlite_connection_table.count(id_curr_thread);
+ MTRY_BL(0 != pairCount);
+
+ DRM_TAPPS_FRQ_LOG("g_dtapps_sqlite_connection_table[id_curr_thread]->countOpenConnection=[%d], g_dtapps_sqlite_connection_table[id_curr_thread]->pDBConnection=[0x%x]", g_dtapps_sqlite_connection_table[id_curr_thread]->countOpenConnection, g_dtapps_sqlite_connection_table[id_curr_thread]->pDBConnection);
+
+ pDBConnection = g_dtapps_sqlite_connection_table[id_curr_thread]->pDBConnection;
+
+ DRM_TAPPS_LOG("pairCount=[%u], g_dtapps_sqlite_connection_table[connectionIterator]=[0x%x]", pairCount, g_dtapps_sqlite_connection_table[id_curr_thread]);
+ DRM_TAPPS_LOG(" This fn finishes successfully..pDBConnection=[0x%x]", pDBConnection);
+ DRM_TAPPS_FRQ_LOG("pDBConnection=[0x%x]",pDBConnection);
+
+ return TRUE;
+
+MCATCH_B
+ DRM_TAPPS_EXCEPTION("This fn fails.. pDBConnection=[0x%x]", pDBConnection);
+
+ return FALSE;
+}
+
+BOOL DTappsDBClose(const char* CallingFun)
+{
+ DRM_TAPPS_LOG("Inside %s Calling function = %s", __func__, CallingFun);
+
+ TAPPSDbApiLock Dblock;
+ unsigned int pairCount;
+ sqlite3_stmt* pstmt = NULL;
+ dtappsThreadID id_curr_thread = drmgettid();
+ int countConnection;
+ sqlite3 *pDBConnection = NULL;
+ int result = SQLITE_ERROR;
+
+ DRM_TAPPS_SECURE_LOG("DB-OPEN-CLOSE [%s]Parent Process ID=[%ld]:Process-ID=[%ld]:Thread-ID=[%ld], id_curr_thread=[%ld]",__func__,getppid(),getpid(),drmgettid(), id_curr_thread);
+
+ pairCount = g_dtapps_sqlite_connection_table.count(id_curr_thread);
+ MTRY_BL(0 != pairCount);
+
+ DRM_TAPPS_FRQ_LOG("g_dtapps_sqlite_connection_table[id_curr_thread]->countOpenConnection=[%d], g_dtapps_sqlite_connection_table[id_curr_thread]->pDBConnection=[0x%x] \n", g_dtapps_sqlite_connection_table[id_curr_thread]->countOpenConnection, g_dtapps_sqlite_connection_table[id_curr_thread]->pDBConnection);
+
+ --(g_dtapps_sqlite_connection_table[id_curr_thread]->countOpenConnection);
+ countConnection = g_dtapps_sqlite_connection_table[id_curr_thread]->countOpenConnection;
+
+ DRM_TAPPS_LOG(" countConnection=[%d] ", countConnection);
+
+ if (0 == countConnection)
+ {
+ DRM_TAPPS_LOG("closing DB connection info ");
+
+ pDBConnection = g_dtapps_sqlite_connection_table[id_curr_thread]->pDBConnection;
+
+ DRM_TAPPS_LOG("pairCount=[%u], g_sqlite_connection_table[connectionIterator]=[0x%x]", pairCount, g_dtapps_sqlite_connection_table[id_curr_thread]);
+ DRM_TAPPS_LOG("erasing map entry..pDBConnection=[0x%x]", pDBConnection);
+
+ g_dtapps_sqlite_connection_table.erase(id_curr_thread);
+
+ DRM_TAPPS_LOG("finalizing all statements..pDBConnection=[0x%x]", pDBConnection);
+
+ while ((pstmt = sqlite3_next_stmt(pDBConnection, pstmt)) != NULL) // prevent fix
+ {
+ DRM_TAPPS_LOG("finalizing DB statement..pstmt=[0x%x]", pstmt);
+ sqlite3_finalize(pstmt);
+ }
+
+ DRM_TAPPS_LOG(" Closing DB connection..pDBConnection=[0x%x]", pDBConnection);
+
+ result = db_util_close(pDBConnection);
+ if(result != SQLITE_OK)
+ {
+ DRM_TAPPS_EXCEPTION("SQLite Close fails. errmsg:%s", sqlite3_errmsg(pDBConnection));
+ MTHROW_BL
+ }
+ }
+
+ DRM_TAPPS_LOG("This fn finishes successfully..pDBConnection=[0x%x]", pDBConnection);
+
+ return TRUE;
+
+MCATCH_B
+
+ DRM_TAPPS_EXCEPTION(" This fn fails.. pDBConnection=[0x%x]", pDBConnection);
+
+ return FALSE;
+}
+
+BOOL DTappsDBBeginImmedTrans (const char* CallingFun)
+{
+ DRM_TAPPS_LOG("Inside %s, Calling function = %s", __func__, CallingFun);
+
+ unsigned int pairCount;
+ dtappsThreadID id_curr_thread = drmgettid();
+ sqlite3* pDBConnection = NULL;
+
+ int count_try_db=0,rc = -1;
+
+ DRM_TAPPS_SECURE_LOG("DB-OPEN-CLOSE-BEG-COM-RB [%s]Parent Process ID=[%ld]:Process-ID=[%ld]:Thread-ID=[%ld], id_curr_thread=[%ld]",__func__,getppid(),getpid(),drmgettid(), id_curr_thread);
+
+ pairCount = g_dtapps_sqlite_connection_table.count(id_curr_thread);
+ MTRY_BL(0 != pairCount);
+
+ DRM_TAPPS_FRQ_LOG("g_dtapps_sqlite_connection_table[id_curr_thread]->countOpenConnection=[%d], g_dtapps_sqlite_connection_table[id_curr_thread]->pDBConnection=[0x%x]", __func__, g_dtapps_sqlite_connection_table[id_curr_thread]->countOpenConnection, g_dtapps_sqlite_connection_table[id_curr_thread]->pDBConnection);
+
+ pDBConnection = g_dtapps_sqlite_connection_table[id_curr_thread]->pDBConnection;
+
+ DRM_TAPPS_LOG("pairCount=[%u], g_dtapps_sqlite_connection_table[connectionIterator]=[0x%x]", pairCount, g_dtapps_sqlite_connection_table[id_curr_thread]);
+ DRM_TAPPS_LOG("Beginning DB operations..pDBConnection=[0x%x]", pDBConnection);
+
+ DRM_TAPPS_FRQ_LOG("pDBConnection=[0x%x]",pDBConnection);
+
+ do
+ {
+ DRM_TAPPS_LOG("START BEGIN");
+ rc = sqlite3_exec (pDBConnection, DTAPPS_SQLITE3_SQL_BEGIN_IMMEDIATE, NULL, NULL, NULL);
+
+ DRM_TAPPS_FRQ_LOG("START BEGIN rc=%d", rc);
+ if (rc != SQLITE_OK)
+ {
+ DRM_TAPPS_FRQ_LOG("pDBConnection=0x%x rc=%d ErrMsg:%s", pDBConnection, rc, sqlite3_errmsg(pDBConnection));
+ if (rc == SQLITE_BUSY)
+ {
+ dtapps_sleep(2, 0);
+ DRM_TAPPS_FRQ_LOG("Tried [%d] times to begin", count_try_db);
+ count_try_db++;
+
+ if (count_try_db >= (int)__DTAPPS_DB_SQLITE_RETRY__)
+ {
+ DRM_TAPPS_EXCEPTION("Error pDBConnection=0x%x rc=%d ErrMsg:%s", pDBConnection, rc, sqlite3_errmsg(pDBConnection));
+ MTHROW_BL
+ }
+ }
+ else
+ {
+ DRM_TAPPS_EXCEPTION("Error pDBConnection=0x%x rc=%d ErrMsg:%s", pDBConnection, rc, sqlite3_errmsg(pDBConnection));
+ MTHROW_BL
+ }
+ }
+ else
+ {
+ DRM_TAPPS_LOG("begin SUCCESS count_try_db=%d", count_try_db);
+ break;
+ }
+ } while(1);
+
+ DRM_TAPPS_LOG("This fn finishes successfully..pDBConnection=[0x%x]", pDBConnection);
+
+ return TRUE;
+
+MCATCH_B
+ DRM_TAPPS_EXCEPTION("This fn fails.. pDBConnection=[0x%x]", pDBConnection);
+ return FALSE;
+}
+
+BOOL DTappsDBCommit(const char* CallingFun)
+{
+ DRM_TAPPS_LOG("Inside %s, Calling function = %s", __func__,CallingFun);
+ unsigned int pairCount;
+ dtappsThreadID id_curr_thread = drmgettid();
+ sqlite3* pDBConnection = NULL;
+
+ int count_try_db_commit=0,rc = -1;
+
+ DRM_TAPPS_SECURE_LOG("DB-OPEN-CLOSE-BEG-COM-RB [%s]Parent Process ID=[%ld]:Process-ID=[%ld]:Thread-ID=[%ld], id_curr_thread=[%ld]",__func__,getppid(),getpid(),drmgettid(), id_curr_thread);
+
+ pairCount = g_dtapps_sqlite_connection_table.count(id_curr_thread);
+ MTRY_BL(1 == pairCount);
+
+ DRM_TAPPS_FRQ_LOG("g_dtapps_sqlite_connection_table[id_curr_thread]->countOpenConnection=[%d], g_dtapps_sqlite_connection_table[id_curr_thread]->pDBConnection=[0x%x] \n", g_dtapps_sqlite_connection_table[id_curr_thread]->countOpenConnection, g_dtapps_sqlite_connection_table[id_curr_thread]->pDBConnection);
+
+ pDBConnection = g_dtapps_sqlite_connection_table[id_curr_thread]->pDBConnection;
+
+ DRM_TAPPS_LOG("pairCount=[%u], g_dtapps_sqlite_connection_table[connectionIterator]=[0x%x]", pairCount, g_dtapps_sqlite_connection_table[id_curr_thread]);
+ DRM_TAPPS_LOG("Commiting DB operations..pDBConnection=[0x%x]", pDBConnection);
+ DRM_TAPPS_FRQ_LOG("pDBConnection=[0x%x]",pDBConnection);
+
+ do
+ {
+ DRM_TAPPS_FRQ_LOG("START Commit");
+ rc = sqlite3_exec (pDBConnection, DTAPPS_SQLITE3_SQL_COMMIT, NULL, NULL, NULL);
+ DRM_TAPPS_FRQ_LOG("START Commit rc=%d", rc);
+
+ if (rc != SQLITE_OK)
+ {
+ DRM_TAPPS_FRQ_LOG("pDBConnection=0x%x rc=%d ErrMsg:%s", pDBConnection, rc, sqlite3_errmsg(pDBConnection));
+
+ if (rc == SQLITE_BUSY)
+ {
+ dtapps_sleep(2, 0);
+ DRM_TAPPS_FRQ_LOG("Tried [%d] times to Commit", count_try_db_commit);
+ count_try_db_commit++;
+ if (count_try_db_commit >= (int)__DTAPPS_DB_SQLITE_RETRY__)
+ {
+ DRM_TAPPS_EXCEPTION("Error pDBConnection=0x%x rc=%d ErrMsg:%s", pDBConnection, rc, sqlite3_errmsg(pDBConnection));
+ MTHROW_BL
+ }
+ }
+ else
+ {
+ DRM_TAPPS_EXCEPTION("Error pDBConnection=0x%x rc=%d ErrMsg:%s", pDBConnection, rc, sqlite3_errmsg(pDBConnection));
+ MTHROW_BL
+ }
+ }
+ else
+ {
+ DRM_TAPPS_FRQ_LOG("Commit SUCCESS count_try_db_commit=%d", count_try_db_commit);
+ break;
+ }
+ } while(1);
+
+ DRM_TAPPS_LOG("This fn finishes successfully..pDBConnection=[0x%x]", pDBConnection);
+
+ return TRUE;
+
+MCATCH_B
+ DRM_TAPPS_EXCEPTION("[%s] This fn fails.. pDBConnection=[0x%x]", pDBConnection);
+
+ return FALSE;
+}
+
+BOOL DTappsDBRollback (const char* CallingFun)
+{
+ DRM_TAPPS_LOG("Inside %s, Calling function = %s", __func__,CallingFun);
+
+ unsigned int pairCount;
+ dtappsThreadID id_curr_thread = drmgettid();
+ sqlite3* pDBConnection = NULL;
+
+ int count_try_db_rollback = 0, rc = -1;
+
+ DRM_TAPPS_SECURE_LOG("DB-OPEN-CLOSE-BEG-COM-RB [%s]Parent Process ID=[%ld]:Process-ID=[%ld]:Thread-ID=[%ld], id_curr_thread=[%ld]",__func__,getppid(),getpid(),drmgettid(), id_curr_thread);
+
+ pairCount = g_dtapps_sqlite_connection_table.count(id_curr_thread);
+ MTRY_BL(1 == pairCount);
+
+ DRM_TAPPS_SECURE_LOG("[%s] g_dtapps_sqlite_connection_table[id_curr_thread]->countOpenConnection=[%d], g_dtapps_sqlite_connection_table[id_curr_thread]->pDBConnection=[0x%x]", __func__, g_dtapps_sqlite_connection_table[id_curr_thread]->countOpenConnection, g_dtapps_sqlite_connection_table[id_curr_thread]->pDBConnection);
+
+ pDBConnection = g_dtapps_sqlite_connection_table[id_curr_thread]->pDBConnection;
+
+ DRM_TAPPS_LOG("pairCount=[%u], g_sqlite_connection_table[connectionIterator]=[0x%x]", __func__, pairCount, g_dtapps_sqlite_connection_table[id_curr_thread]);
+ DRM_TAPPS_LOG("Rollback DB operations..pDBConnection=[0x%x]", pDBConnection);
+
+ DRM_TAPPS_FRQ_LOG("[%s] pDBConnection=[0x%x]",pDBConnection);
+
+ do
+ {
+ DRM_TAPPS_FRQ_LOG("START Rollback");
+ rc = sqlite3_exec (pDBConnection, DTAPPS_SQLITE3_SQL_ROLLBACK, NULL, NULL, NULL);
+ DRM_TAPPS_FRQ_LOG("START Rollback rc=%d",rc);
+
+ if (rc != SQLITE_OK)
+ {
+ DRM_TAPPS_FRQ_LOG("pDBConnection=0x%x rc=%d ErrMsg:%s",pDBConnection,rc,sqlite3_errmsg(pDBConnection));
+
+ if(rc == SQLITE_BUSY)
+ {
+ dtapps_sleep(2,0);
+ DRM_TAPPS_FRQ_LOG("Tried [%d] times to Rollback",count_try_db_rollback);
+ count_try_db_rollback++;
+ if(count_try_db_rollback >= (int)__DTAPPS_DB_SQLITE_RETRY__)
+ {
+ DRM_TAPPS_EXCEPTION("Error pDBConnection=0x%x rc=%d ErrMsg:%s",pDBConnection,rc,sqlite3_errmsg(pDBConnection));
+ MTHROW_BL
+ }
+ }
+ else
+ {
+ DRM_TAPPS_EXCEPTION("Error pDBConnection=0x%x rc=%d ErrMsg:%s",pDBConnection,rc,sqlite3_errmsg(pDBConnection));
+ MTHROW_BL
+ }
+ }
+ else
+ {
+ DRM_TAPPS_FRQ_LOG("Rollback SUCCESS count_try_db_rollback=%d",count_try_db_rollback);
+ break;
+ }
+ } while(1);
+
+ DRM_TAPPS_LOG("This fn finishes successfully..pDBConnection=[0x%x]", pDBConnection);
+
+ return TRUE;
+
+MCATCH_B
+ DRM_TAPPS_EXCEPTION("This fn fails.. pDBConnection=[0x%x]", pDBConnection);
+
+ return FALSE;
+}
+
+
+BOOL DTappsExecuteSQL(void* pDB, const char* query)
+{
+ int count_try_db_exe = 0, rc = 0;
+ sqlite3* h_db = (sqlite3*)pDB;
+
+ TAPPSDbApiLock Dblock;
+
+ do
+ {
+ rc = sqlite3_exec (h_db, query, NULL, NULL, NULL);
+ DRM_TAPPS_FRQ_LOG("EXECUTE rc=%d", rc);
+
+ if (rc != SQLITE_OK)
+ {
+ if (rc == SQLITE_BUSY)
+ {
+ dtapps_sleep(2, 0);
+ DRM_TAPPS_FRQ_LOG("Tried [%d] times to execute",count_try_db_exe);
+ count_try_db_exe++;
+
+ if (count_try_db_exe >= (int)__DTAPPS_DB_SQLITE_RETRY__)
+ {
+ DRM_TAPPS_EXCEPTION("h_db=0x%x rc=%d ErrMsg:%s count_try_db_exe=%d",h_db,rc,sqlite3_errmsg(h_db),count_try_db_exe);
+ DRM_TAPPS_EXCEPTION("query=[%s]",query);
+ return FALSE;
+ }
+ }
+ else
+ {
+ DRM_TAPPS_EXCEPTION("h_db=0x%x rc=%d ErrMsg:%s", h_db, rc, sqlite3_errmsg(h_db));
+ DRM_TAPPS_EXCEPTION("query=[%s]", query);
+ return FALSE;
+ }
+ }
+ else
+ {
+ DRM_TAPPS_FRQ_LOG("EXECUTE SUCCESS count_try_db_exe=%d", count_try_db_exe);
+ break;
+ }
+ } while(1);
+
+ return TRUE;
+}
+
+
+BOOL DTappsSQLGetTable(void* pDB, const char* query, TAPPSSqliteSelectTable* select_table)
+{
+ int rc = 0;
+ sqlite3* h_db = (sqlite3*)pDB;
+
+ DRM_TAPPS_FRQ_LOG("h_db=0x%x query=%s", h_db,query);
+ TAPPSDbApiLock Dblock;
+ select_table->handle = h_db;
+
+ DRM_TAPPS_FRQ_LOG("select_table->handle=%x", select_table->handle);
+
+ int count_try_db_select = 0;
+
+ do
+ {
+ rc = sqlite3_get_table(h_db, query, &select_table->result, &select_table->n_rows, &select_table->n_cols, NULL);
+
+ DRM_TAPPS_FRQ_LOG("SELECT rc=%d", rc);
+
+ if (rc != SQLITE_OK)
+ {
+ if (rc == SQLITE_BUSY)
+ {
+ dtapps_sleep(2,0);
+ DRM_TAPPS_FRQ_LOG("SELECT Tried [%d] times to select \n",count_try_db_select);
+
+ count_try_db_select++;
+
+ if(count_try_db_select >= (int)__DTAPPS_DB_SQLITE_RETRY__)
+ {
+ DRM_TAPPS_EXCEPTION("SELECT h_db=0x%x rc=%d ErrMsg:%s count_try_db_select=%d \n",h_db,rc,sqlite3_errmsg(h_db),count_try_db_select);
+ DRM_TAPPS_EXCEPTION("query=[%s] \n",query);
+
+ return FALSE;
+ }
+ }
+ else
+ {
+ DRM_TAPPS_EXCEPTION("SELECT h_db=0x%x rc=%d ErrMsg:%s \n",h_db,rc,sqlite3_errmsg(h_db));
+ DRM_TAPPS_EXCEPTION("%s query=[%s] \n",query);
+
+ return FALSE;
+ }
+ }
+ else
+ {
+ DRM_TAPPS_FRQ_LOG("SELECT SUCCESS count_try_db_select=%d \n",count_try_db_select);
+
+ break;
+ }
+ } while(1);
+
+ DRM_TAPPS_FRQ_LOG("n_rows=%d n_cols=%d \n",select_table->n_rows, select_table->n_cols);
+
+ return TRUE;
+}
+
+extern const char* dtappsCreateTableSQLData[];
+
+char* DTappsGetSQLCreateTable(const char* tableName)
+{
+ int index=0;
+
+ if(!tableName)
+ {
+ return NULL;
+ }
+
+ DRM_TAPPS_FRQ_LOG("tableName = %s",tableName);
+
+ while(dtappsCreateTableSQLData[index])
+ {
+ if(TAPPS_strnicmp( dtappsCreateTableSQLData[index],tableName,TAPPS_STRLEN(tableName))==0)
+ {
+ char* sql = (char*)dtappsCreateTableSQLData[index];
+ sql = sql + TAPPS_STRLEN(dtappsCreateTableSQLData[index])+1;
+
+ DRM_TAPPS_FRQ_LOG("sql query = %s",sql);
+
+ return sql;
+ }
+ else
+ {
+ index++;
+ }
+ }
+
+ DRM_TAPPS_EXCEPTION("Specified Table Name is not Valid!!!");
+
+ return NULL;
+}
+
+void* DTappsStmtPrepare(void* pDB, const char* query)
+{
+ int rc = 0;
+ sqlite3* h_db = (sqlite3*)pDB;
+ sqlite3_stmt* stmt = 0;
+
+ DRM_TAPPS_FRQ_LOG("h_db=0x%x query=%s \n",h_db,query);
+
+ TAPPSDbApiLock Dblock;
+
+ if(0 == TAPPS_strnicmp(query, "SELECT", 6))
+ {
+ DRM_TAPPS_EXCEPTION("Doesn't support 'Select' query h_db=0x%x query=%s \n",h_db,query);
+
+ return NULL;
+ }
+
+ rc = sqlite3_prepare( h_db, query, -1, &stmt, NULL);
+
+ DRM_TAPPS_FRQ_LOG("%s: rc=%d query=%s stmt=0x%x \n",__func__,rc,query,stmt);
+
+ if (rc != SQLITE_OK)
+ {
+ DRM_TAPPS_EXCEPTION("DTappsStmtPrepare: h_db=0x%x err: %s \n",h_db,sqlite3_errmsg(h_db));
+ DRM_TAPPS_EXCEPTION("DTappsStmtPrepare: query: %s\n", query);
+
+ return NULL;
+ }
+
+ return stmt;
+}
+
+
+int DTappsStmtBindParam (
+ void* pStmt,
+ unsigned int dIdx,
+ unsigned int Type,
+ void* pParam,
+ unsigned int dParamSize )
+{
+ int rc = 0;
+ sqlite3_stmt* stmt = (sqlite3_stmt*)pStmt;
+
+ DRM_TAPPS_FRQ_LOG("Enter \n");
+
+ TAPPSDbApiLock Dblock;
+
+ if(stmt == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("DTappsStmtBindParam: stmt is NULL \n");
+
+ return FALSE;
+ }
+
+ /*
+ * Notice:
+ * The parameter index in SQL starts from 1 in sqlite3.
+ */
+ switch(Type)
+ {
+ case TAPPSDB_TYPE_NONE:
+ rc = sqlite3_bind_null( stmt, dIdx+1);
+
+ break;
+
+ case TAPPSDB_TYPE_INT:
+ rc = sqlite3_bind_int( stmt, dIdx+1, *(int*)pParam);
+ DRM_TAPPS_FRQ_LOG(" rc=%d type=%d pParam=%d \n",rc,Type,*(int*)pParam);
+
+ break;
+
+ case TAPPSDB_TYPE_DATETIME:
+
+ case TAPPSDB_TYPE_CHAR:
+
+ case TAPPSDB_TYPE_VARCHAR:
+ rc = sqlite3_bind_text( stmt, dIdx+1, (char*)pParam, dParamSize, SQLITE_TRANSIENT);
+ DRM_TAPPS_FRQ_LOG("rc=%d type=%d dParamSize=%d pParam=%s \n",rc,Type,dParamSize,pParam);
+
+ break;
+
+ case TAPPSDB_TYPE_BINARY:
+
+ case TAPPSDB_TYPE_BLOB:
+ #if 0
+ {
+ char* packet64=NULL;
+ unsigned int packet64_size=0;
+ if(CMStringUtil::GetBase64Encode((unsigned char*)pParam,dParamSize, &packet64) == true)
+ {
+ packet64_size = MSTRLEN(packet64);
+ rc = sqlite3_bind_blob( stmt, dIdx+1, packet64, packet64_size, SQLITE_TRANSIENT);
+ DRM_OMA_FRQ_LOG("%s: rc=%d type=%d packet64_size=%d packet64=%s \n",__func__,rc,Type,packet64_size,packet64);
+ if(packet64) MDELETES0(packet64);
+ }
+ }
+ #endif
+ break;
+
+ case TAPPSDB_TYPE_UNKNOWN:
+
+ default:
+ break;
+ }//switch
+
+ if(rc != SQLITE_OK)
+ {
+ DRM_TAPPS_EXCEPTION("DTappsStmtBindParam: errno: %d\n", rc);
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+int DTappsStmtExecute (void* pStmt)
+{
+ int CntTryStmtExe=0, rc =-1;
+ sqlite3_stmt* stmt = (sqlite3_stmt*)pStmt;
+
+ DRM_TAPPS_FRQ_LOG("%s:stmt=0x%x \n",__func__,stmt);
+
+ TAPPSDbApiLock Dblock;
+
+ if(stmt == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("stmt is NULL \n");
+
+ return FALSE;
+ }
+
+ do
+ {
+ rc = sqlite3_step(stmt);
+
+ DRM_TAPPS_FRQ_LOG(" rc=%d \n",rc);
+
+ if ( rc != SQLITE_DONE )
+ {
+ if(rc == SQLITE_BUSY)
+ {
+ dtapps_sleep(2,0);
+ DRM_TAPPS_FRQ_LOG("Tried [%d] times to execute stmt \n",CntTryStmtExe);
+
+ CntTryStmtExe++;
+
+ if(CntTryStmtExe >= (int)__DTAPPS_DB_SQLITE_RETRY__)
+ {
+ DRM_TAPPS_EXCEPTION("stmt=0x%x rc=%d CntTryStmtExe=%d \n",stmt,rc,CntTryStmtExe);
+
+ return FALSE;
+ }
+ }
+ else
+ {
+ DRM_TAPPS_EXCEPTION("stmt=0x%x rc=%d \n",stmt,rc);
+
+ return FALSE;
+ }
+ }
+ else
+ {
+ DRM_TAPPS_FRQ_LOG("STMT EXECUTE SUCCESS CntTryStmtExe=%d \n",CntTryStmtExe);
+
+ return TRUE;
+ }
+ } while(1);
+}
+
+
+int DTappsStmtRelease (void* pStmt)
+{
+ int rc = 0;
+ sqlite3_stmt* stmt = (sqlite3_stmt*)pStmt;
+ DRM_TAPPS_FRQ_LOG("%s:Enter \n",__func__);
+ TAPPSDbApiLock Dblock;
+ if (!stmt)
+ {
+ return FALSE;
+ }
+
+ rc = sqlite3_finalize (stmt);
+
+ DRM_TAPPS_FRQ_LOG("rc=%d \n",rc);
+
+ if ( rc != SQLITE_OK )
+ {
+ DRM_TAPPS_EXCEPTION("DTappsStmtRelease() Errmsg ; %d \n", rc);
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+BOOL DTapps_DB_Install(const char* sql_query)
+{
+ void *pDb = NULL;
+ BOOL ret_value = FALSE;
+
+ if(sql_query == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("Parameter NULL!!!, sql_query = %p",sql_query);
+
+ return FALSE;
+ }
+
+ DRM_TAPPS_LOG("Open DB......");
+
+ ret_value = DTappsDBOpen(pDb,__func__);
+
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("DB Open Failed!! ret_value = %d",ret_value);
+
+ return FALSE;
+ }
+
+ DRM_TAPPS_LOG("Begin Transaction........");
+
+ ret_value = DTappsDBBeginImmedTrans(__func__);
+
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("DB Begin Transaction ret_value = %d",ret_value);
+
+ goto Error_Exit;
+ }
+
+ DRM_TAPPS_LOG("Execute SQL to Insert Contents into Table........");
+
+ ret_value = DTappsExecuteSQL(pDb,sql_query);
+
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("Execute SQL Query Failed!! ret_value = %d",ret_value);
+
+ goto Error_Exit;
+ }
+
+ DRM_TAPPS_LOG("Commit DB........");
+
+ ret_value = DTappsDBCommit(__func__);
+
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("Commit DB Failed!! ret_value = %d",ret_value);
+
+ goto Error_Exit;
+ }
+
+ DRM_TAPPS_LOG("Close DB........");
+
+ ret_value = DTappsDBClose(__func__);
+
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("Close DB Failed!! ret_value = %d",ret_value);
+
+ goto Error_Exit;
+ }
+
+ DRM_TAPPS_LOG("Install DB Operartion Successful!!!");
+
+ return TRUE;
+
+Error_Exit:
+
+ ret_value = DTappsDBRollback (__func__);
+
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("Rollback DB Failed!! ret_value = %d",ret_value);
+ }
+
+ ret_value = DTappsDBClose(__func__);
+
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("Close DB Failed!! ret_value = %d",ret_value);
+ }
+
+ return FALSE;
+}
+
+BOOL DTapps_Read_DB(const char* sql_query, TAPPSSqliteSelectTable* select_table)
+{
+ void *pDb = NULL;
+ BOOL ret_value = FALSE;
+
+ if(sql_query == NULL || select_table == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("Parameters NULL, sql_query = %p, select_table = %p",sql_query,select_table);
+
+ return FALSE;
+ }
+
+ DRM_TAPPS_LOG("Open DB......");
+
+ ret_value = DTappsDBOpen(pDb,__func__);
+
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("DB Open Failed!! ret_value = %d",ret_value);
+
+ return FALSE;
+ }
+
+ DRM_TAPPS_LOG("Begin Transaction........");
+
+ ret_value = DTappsDBBeginImmedTrans(__func__);
+
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("DB Begin Transaction Failed!! ret_value = %d",ret_value);
+
+ goto Error_Exit;
+ }
+
+ DRM_TAPPS_LOG("Get the Result Table........");
+
+ ret_value = DTappsSQLGetTable(pDb,sql_query,select_table);
+
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("DB Get Table failed!! ret_value = %d",ret_value);
+
+ goto Error_Exit;
+ }
+
+ DRM_TAPPS_LOG("Close DB........");
+
+ ret_value = DTappsDBClose(__func__);
+
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("DB Close failed!! ret_value = %d",ret_value);
+
+ goto Error_Exit;
+ }
+
+ DRM_TAPPS_LOG("Reading from DB Successful!!!");
+
+ return TRUE;
+
+Error_Exit:
+
+ ret_value = DTappsDBRollback (__func__);
+
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("Rollback DB Failed!! ret_value = %d",ret_value);
+ }
+
+ ret_value = DTappsDBClose(__func__);
+
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("Close DB Failed!! ret_value = %d",ret_value);
+ }
+
+ DRM_TAPPS_EXCEPTION("Reading DB function failed!!!");
+
+ return FALSE;
+}
diff --git a/tappsd/src/intf/drm_intf_tapps.cpp b/tappsd/src/intf/drm_intf_tapps.cpp
new file mode 100644
index 0000000..6257e57
--- /dev/null
+++ b/tappsd/src/intf/drm_intf_tapps.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 drm_intf_tapps.cpp
+ * @brief This file includes definitions of the drm TAPPS intf APIs.
+ */
+
+#include "drm_intf_tapps.h"
+
+/* String Operations */
+#ifdef _TAPPS_DEBUG_ENABLE_
+unsigned int TAPPS_gstrlcat(char* s1,const char* s2,unsigned int destsize,const char* funName, unsigned int lineno)
+{
+ unsigned int ret_g_strlcat = (unsigned int)g_strlcat(s1, s2, destsize);
+
+ if(ret_g_strlcat >= (unsigned int)destsize)
+ {
+ DRM_TAPPS_EXCEPTION("Truncation occured during concatenation at [%s:%u] s1=%s s2=%s destsize=%u ret_g_strlcpy=%u \n",funName,lineno,s1,s2,destsize,ret_g_strlcat);
+ }
+ else
+ {
+ DRM_TAPPS_FRQ_LOG("Concatenation Successful at [%s:%u] s1=%s s2=%s destsize=%u ret_g_strlcpy=%u \n",funName,lineno,s1,s2,destsize,ret_g_strlcat);
+ }
+
+ return ret_g_strlcat;
+}
+
+unsigned int TAPPS_gstrlcpy(char* s1,const char* s2,unsigned int destsize,const char* funName, unsigned int lineno)
+{
+ unsigned int ret_g_strlcpy = (unsigned int)g_strlcpy(s1, s2, destsize);
+
+ if(ret_g_strlcpy >= (unsigned int)destsize)
+ {
+ DRM_TAPPS_EXCEPTION("Truncation occured during copying at [%s:%u] s1=%s s2=%s destsize=%u ret_g_strlcpy=%u \n",funName,lineno,s1,s2,destsize,ret_g_strlcpy);
+ }
+ else
+ {
+ DRM_TAPPS_FRQ_LOG("Copy Successful at [%s:%u] s1=%s s2=%s destsize=%u ret_g_strlcpy=%u \n",funName,lineno,s1,s2,destsize,ret_g_strlcpy);
+ }
+
+ return ret_g_strlcpy;
+}
+
+unsigned int TAPPS_strlen(const char* s,const char* funName, unsigned int lineno)
+{
+ DRM_TAPPS_FRQ_LOG("Function = %s, Line number = %u",funName,lineno);
+
+ return strlen(s);
+}
+#endif
+
+int TAPPS_strnicmp(const char * s1, const char * s2, unsigned int sz)
+{
+ int tmp1=0, tmp2=0;
+
+ unsigned int idx =0;
+
+ do
+ {
+ if ( ((tmp1 = (unsigned char)(*(s1++))) >= 'A') && (tmp1 <= 'Z') )
+ tmp1 -= ('A' - 'a');
+
+ if ( ((tmp2 = (unsigned char)(*(s2++))) >= 'A') && (tmp2 <= 'Z') )
+ tmp2 -= ('A' - 'a');
+
+ idx++;
+ } while ( tmp1 && (tmp1== tmp2) && idx < sz);
+
+ return (tmp1 - tmp2);
+}
+
+
+/* Mutex Handling */
+
+int dtapps_mutex_lock (dtappslockarg dtapps_mutex)
+{
+ int retval=-1;
+
+ DRM_TAPPS_FRQ_LOG( "%s MUT-LK-ULK Thread [%d] trying to lock the Mutex=0x%x \n",__func__,drmgettid(),dtapps_mutex);
+
+ retval = pthread_mutex_lock(dtapps_mutex);
+
+ if(retval != 0)
+ {
+ if(retval == EDEADLK)
+ {
+ DRM_TAPPS_FRQ_LOG("Mutex is already locked by the same thread \n");
+ }
+ else
+ {
+ DRM_TAPPS_EXCEPTION( "Error locking mutex %d \n", retval);
+ perror("\n drm_mutex_lock:Error:");
+ }
+ retval=-1;
+ }
+ else
+ {
+ DRM_TAPPS_FRQ_LOG( "Mutex lock is successful \n");
+ }
+ DRM_TAPPS_FRQ_LOG( "%s retval=%d \n",__func__,retval);
+
+ return retval;
+}
+
+
+int dtapps_mutex_unlock (dtappslockarg dtapps_mutex)
+{
+ int status=-1;
+
+ DRM_TAPPS_FRQ_LOG( "%s MUT-LK-ULK Thread [%d] trying to unlock the Mutex=0x%x \n",__func__,drmgettid(),dtapps_mutex);
+
+ status = pthread_mutex_unlock(dtapps_mutex);
+
+ if(status != 0)
+ {
+ DRM_TAPPS_EXCEPTION( "Error unlocking mutex:return value=[%d] \n", status);
+ perror("\n drm_mutex_unlock:Error:");
+ status = -1;
+ }
+ else
+ {
+ DRM_TAPPS_FRQ_LOG( "Mutex unlocked is successful :return value=[%d] \n",status);
+ }
+
+ DRM_TAPPS_FRQ_LOG( "%s status=%d \n",__func__,status);
+
+ return status;
+}
+
+void dtapps_sleep(unsigned int TimeInSec,unsigned int TimeInMicroSec)
+{
+ struct timeval tv;
+ int retval= -1;
+ tv.tv_sec = TimeInSec;
+ tv.tv_usec = TimeInMicroSec;
+
+ DRM_TAPPS_FRQ_LOG("%s TimeInSec =%u TimeInMicroSec=%u \n",__func__,tv.tv_sec,tv.tv_usec);
+
+ retval = select(0, NULL, NULL, NULL, &tv);
+
+ DRM_TAPPS_FRQ_LOG("%s select retval=%d \n",__func__,retval);
+}
diff --git a/tappsd/src/rights/DTapps2Rights.cpp b/tappsd/src/rights/DTapps2Rights.cpp
new file mode 100644
index 0000000..3f0143e
--- /dev/null
+++ b/tappsd/src/rights/DTapps2Rights.cpp
@@ -0,0 +1,1288 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 DTapps2Rights.cpp
+ * @brief This file includes functions relating to Rights.
+ */
+
+#include <string>
+
+#include "TADC_Core.h"
+#include "TADC_IF.h"
+#include "drm-tizen-error.h"
+
+#include "TADC_Util.h"
+
+#include "DTapps2Rights.h"
+#include "DTapps2SqliteDB.h"
+#include "DTapps2HMAC.h"
+#include "DTapps2Base64.h"
+#include "DTapps2Time.h"
+
+/* Validation and Installation of the Constraints Structure */
+int DTappsValidateConstraints(DTAPPS_CONSTRAINTS* st_const, DTAPPS_OPERATION opr)
+{
+ int ret = TADC_LICENSE_VALID;
+ char DUID[DTAPPS_DUID_SIZE] = {0, };
+ unsigned char zeroduid[DTAPPS_DUID_SIZE] = {0, };
+ int retDeviceInfo = 0;
+
+ if (st_const == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("Invalid Paramter st_const = %p", st_const);
+ ret = TADC_PARAMETER_ERROR;
+ goto Error_Exit;
+ }
+
+ /* Check for DUID */
+ if (DTAPPS_MEMCMP(st_const->DUID, zeroduid, DTAPPS_DUID_SIZE))
+ {
+ DRM_TAPPS_LOG("st_const->DUID = %s", st_const->DUID);
+ if(opr == DTAPPS_VERIFY || opr == DTAPPS_INSTALL)
+ {
+ retDeviceInfo = TADC_IF_GetDUID(DUID);
+ if (retDeviceInfo < 0)
+ {
+ DRM_TAPPS_EXCEPTION("Retrieve for DUID Failed!!! DUID = %s, duid_len = %d", DUID, strlen(DUID));
+ return TADC_LICENSE_UNKNOWN_ERROR;
+ }
+ if (!(DTAPPS_MEMCMP(st_const->DUID, DUID, DTAPPS_DUID_SIZE)))
+ {
+ DRM_TAPPS_LOG("DUID match!! st_const->DUID = %s, DUID = %s", st_const->DUID, DUID);
+ ret = TADC_LICENSE_VALID;
+ }
+ else
+ {
+ DRM_TAPPS_EXCEPTION("DUID don't match!!! st_const->DUID = %s, DUID = %s", st_const->DUID, DUID);
+ ret = TADC_LICENSE_DUID_MISMATCH;
+ goto Error_Exit;
+ }
+ }
+ }
+ DRM_TAPPS_LOG("ret = %d", ret);
+ return ret;
+
+Error_Exit:
+ DRM_TAPPS_EXCEPTION("Validate Constraints failed!!!, ret = %d", ret);
+ return ret;
+}
+
+int DTappsInstallLicense(const char* declicbuffer)
+{
+ unsigned char* db_buffer_org = NULL;
+ unsigned char db_buffer_enc[512] = {0, };
+ int len_enc = 0, check_ret = 0;
+ unsigned char *pDevKey = NULL;
+ unsigned int DevKeyLen = 0;
+ unsigned char hash[32] = {0, };
+ unsigned char hash_enc[64] = {0, };
+ unsigned int hash_len = 0;
+ int check = TADC_LICENSE_VALID;
+
+ BOOL isOk = FALSE;
+ int ret = TADC_SUCCESS;
+
+ unsigned char name[DTAPPS_NAME_SIZE] = {0, };
+ unsigned char nullCek[CEK_SIZE] = {0, };
+
+ char sql_query[2048] = {0, };
+ int len = 0;
+ time_t now = 0;
+ char time_buffer[21] = {0, };
+ T_RO t_RO = {0, };
+
+ DTAPPS_RIGHTS_ROW row;
+
+#ifdef DTAPPS_STORE_CEK_IN_DB
+ AES_KEY key = {{0}};
+ unsigned char *encr_cek = NULL;
+ unsigned int keylen = 0;
+ unsigned int encr_cek_len = 0;
+ unsigned char b64_encr_cek[128] = {0, };
+ unsigned char encr_cek_hash[32] = {0, };
+ unsigned char b64_encr_cek_hash[64] = {0, };
+ unsigned int encr_cek_hash_len = 0;
+#endif
+
+ // Copy necessary fields into structure to be stored in DB
+ DTAPPS_CONSTRAINTS st_constraints = {0, };
+
+ // First Parse the decrypted Licence buffer in order to fill the t_RO buffer and use it to store in DB
+ check_ret = DTappsGetROInfo(declicbuffer, &t_RO, name);
+ if (check_ret < 0)
+ {
+ DRM_TAPPS_EXCEPTION("DTappsGetROInfo Error Code = %x, check_ret = %d", TADC_LICENSEXMLPARSING_ERROR,check_ret);
+ ret = TADC_LICENSEXMLPARSING_ERROR;
+ goto Error_Exit;
+ }
+
+ /* Copy DUID */
+ if (t_RO.t_Permission.t_Individual.DUID != NULL)
+ {
+ DTAPPS_MEMCPY(st_constraints.DUID, t_RO.t_Permission.t_Individual.DUID, TAPPS_STRLEN((const char*)t_RO.t_Permission.t_Individual.DUID));
+ }
+ DRM_TAPPS_LOG("st_constraints.DUID = %s", st_constraints.DUID);
+
+ /* Validation of constraints */
+ check = DTappsValidateConstraints(&st_constraints, DTAPPS_INSTALL);
+ if (check != TADC_LICENSE_VALID)
+ {
+ DRM_TAPPS_LOG("Constraints obtained are NOT VALID!!!, check = %d",check);
+ ret = TADC_LICENSE_INVALID_ERROR;
+ goto Error_Exit;
+ }
+
+ /* Create the contraints buffer to be put in DB */
+ db_buffer_org = (unsigned char*)DTAPPS_MALLOC(sizeof(DTAPPS_CONSTRAINTS));
+ if (db_buffer_org == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("Memory Allocation error , db_buffer_org = %p", db_buffer_org);
+ ret = TADC_MEMAlOC_ERROR;
+ goto Error_Exit;
+ }
+
+ DTAPPS_MEMSET(db_buffer_org, 0x00, sizeof(DTAPPS_CONSTRAINTS));
+ DTAPPS_MEMCPY(db_buffer_org, &st_constraints, sizeof(DTAPPS_CONSTRAINTS));
+
+ /* Calculate the hash - HMAC for the constraints buffer */
+ if (0 == DTappsGetDeviceKey(&pDevKey, &DevKeyLen))
+ {
+ DRM_TAPPS_EXCEPTION("Error in DTAppsGetDeviceKey!!!, pDevKey = %p, DevKeyLen = %d", pDevKey, DevKeyLen);
+ ret = TADC_GET_DEVICEKEY_ERROR;
+ goto Error_Exit;
+ }
+
+ DTappsCalHMACSHA1(pDevKey, (int)DevKeyLen, db_buffer_org, sizeof(DTAPPS_CONSTRAINTS), hash, &hash_len);
+
+ /* Encode the buffer and hash using Base64 and then store it into the DB */
+ /* Base64 Encode the constraints buffer */
+ len_enc = (sizeof(DTAPPS_CONSTRAINTS) + 2) / 3 * 4;
+
+ isOk = DTappsB64Encode(db_buffer_org, sizeof(DTAPPS_CONSTRAINTS), db_buffer_enc, len_enc);
+ if (isOk != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("BASE64 Encoding failure!!!! ret = %d", isOk);
+ ret = TADC_GET_BASE64ENCODE_ERROR;
+ goto Error_Exit;
+ }
+
+ /* Base64 Encode the hash buffer */
+ len_enc = (hash_len + 2) / 3 * 4;
+
+ isOk = DTappsB64Encode(hash, hash_len, hash_enc, len_enc);
+ if (isOk != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("BASE64 Encoding failure!!!! ret = %d", isOk);
+ ret = TADC_GET_BASE64ENCODE_ERROR;
+ goto Error_Exit;
+ }
+
+ DRM_TAPPS_LOG("CEK installation started!!");
+ if (DTAPPS_MEMCMP((void*)t_RO.t_Content.CEK, (void*)nullCek, CEK_SIZE) != 0)
+ {
+#ifdef DTAPPS_STORE_CEK_IN_DB
+ /* Store the CEK in DB */
+ /* First encrypt the CEK , calculate the HASH and then convert both into BASE64 Encoded form */
+ //ceklen = (unsigned int)TAPPS_STRLEN((const char*) t_RO.t_Content.CEK);
+ /* keylen => Should be a multiple of 8 */
+ keylen = CEK_SIZE;
+ encr_cek_len = keylen + 8;
+
+ if ((check_ret = DTAPPS_AES_SET_ENCR_KEY(pDevKey, 128, &key)) != 0)
+ {
+ DRM_TAPPS_EXCEPTION("DTAPPS_AES_SET_ENC_KEY failed!!, check_ret = %d", check_ret);
+ ret = TADC_SET_AES_ENCRYPTKEY_ERROR;
+ goto Error_Exit;
+ }
+
+ encr_cek = (unsigned char*)DTAPPS_MALLOC(encr_cek_len);
+ if (NULL == encr_cek)
+ {
+ DRM_TAPPS_EXCEPTION("Memory Allocation Error!!, encr_cek = %p", encr_cek);
+ ret = TADC_MEMAlOC_ERROR;
+ goto Error_Exit;
+ }
+
+ check_ret = DTAPPS_AES_WRAP_KEY(&key, NULL, encr_cek, t_RO.t_Content.CEK, keylen);
+ if (check_ret <= 0)
+ {
+ DRM_TAPPS_EXCEPTION("DTAPPS_AES_WRAP_KEY failed!!, check_ret = %d", check_ret);
+ ret = TADC_SET_AES_WRAPKEY_ERROR;
+ goto Error_Exit;
+ }
+ DRM_TAPPS_LOG("encr_cek = %s", encr_cek);
+
+ /* Calculate the HASH for Encrypted CEK */
+ DTappsCalHMACSHA1(pDevKey, (int)DevKeyLen, encr_cek, encr_cek_len, encr_cek_hash, &encr_cek_hash_len);
+ DRM_TAPPS_LOG("encr_cek_hash = %s", encr_cek_hash);
+
+ /* Base64 Encode the Encrypted CEK */
+ len_enc = (encr_cek_len + 2) / 3 * 4;
+ isOk = DTappsB64Encode(encr_cek, encr_cek_len, b64_encr_cek, len_enc);
+ if (isOk != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("BASE64 Encoding failure!!!! ret = %d", isOk);
+ ret = TADC_GET_BASE64ENCODE_ERROR;
+ goto Error_Exit;
+ }
+
+ /* Base64 Encode the Hash of Encrypted CEK */
+ len_enc = (encr_cek_hash_len + 2) / 3 * 4;
+ isOk = DTappsB64Encode(encr_cek_hash, encr_cek_hash_len, b64_encr_cek_hash, len_enc);
+ if (isOk != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("BASE64 Encoding failure!!!! ret = %d", isOk);
+ ret = TADC_GET_BASE64ENCODE_ERROR;
+ goto Error_Exit;
+ }
+
+ DRM_TAPPS_LOG("b64_encr_cek = %s, b64_encr_cek_hash = %s", b64_encr_cek, b64_encr_cek_hash);
+#else
+ DRM_TAPPS_LOG("CEK in Secure Storage to be implemented!!!");
+#endif
+ }
+ else
+ {
+ DRM_TAPPS_EXCEPTION("t_RO.t_Content.CEK is null!!");
+ }
+
+ /* Calculate the Time of storage */
+ now = DTAPPS_TIME(NULL);
+ struct tm time_gmt;
+ DTAPPS_GMTIME_THREAD_SAFE(&now, &time_gmt);
+
+ /* Format the time to be stored in the DB buffer - DATETIME format */
+ len = DTAPPS_SNPRINTF(
+ time_buffer,
+ sizeof(time_buffer),
+ "%04d-%02d-%02dT%02d:%02d:%02dZ",
+ time_gmt.tm_year + 1900,
+ time_gmt.tm_mon + 1,
+ time_gmt.tm_mday,
+ time_gmt.tm_hour,
+ time_gmt.tm_min,
+ time_gmt.tm_sec);
+
+ if ((len == -1) || (len >= (int)sizeof(time_buffer)))
+ {
+ DRM_TAPPS_EXCEPTION("snprintf failed , len = %d, sizeof(time_buffer) = %d",len,sizeof(time_buffer));
+ ret = TADC_MEMAlOC_ERROR;
+ goto Error_Exit;
+ }
+ DRM_TAPPS_LOG("time_buffer = %s", time_buffer);
+ DRM_TAPPS_LOG("Constraint_buffer = %s, Constraint_Hash = %s", db_buffer_enc, hash_enc);
+
+ // 2013/04/25 added for db update
+ isOk = DTapps_RIGHTS_SELECT_ONE((char*) t_RO.t_Content.CID, &row);
+
+ // if there is no rights in the db, insert into rights to db
+ if (isOk != TRUE)
+ {
+ DRM_TAPPS_LOG("Insert into dtapps2rights started....");
+ isOk = DTapps_RIGHTS_INSTALL((char*) name, time_buffer,
+ #ifdef DTAPPS_STORE_CEK_IN_DB
+ (char*) b64_encr_cek, (char*) b64_encr_cek_hash,
+ #endif
+ (char*) db_buffer_enc, (char*) hash_enc, (char*) t_RO.t_Content.CID,
+ FALSE);
+ if (isOk != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("DB Installation failure!!!! ret = %d", isOk);
+ ret = TADC_DB_INSTALL_ERROR;
+ goto Error_Exit;
+ }
+ DRM_TAPPS_LOG("DrmTdcInstallLicense Success!!!!!! ret = %d", ret);
+ }
+ // if there is same cid rights exist, update right to db
+ else
+ {
+ DRM_TAPPS_LOG("Update dtapps2rights started....");
+ isOk = DTapps_RIGHTS_INSTALL((char*) name, time_buffer,
+ #ifdef DTAPPS_STORE_CEK_IN_DB
+ (char*) b64_encr_cek, (char*) b64_encr_cek_hash,
+ #endif
+ (char*) db_buffer_enc, (char*) hash_enc, (char*) t_RO.t_Content.CID,
+ TRUE);
+ if (isOk != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("DB Update failure!!!! ret = %d", isOk);
+ ret = TADC_DB_INSTALL_ERROR;
+ goto Error_Exit;
+ }
+ DRM_TAPPS_LOG("DrmTdcInstallLicense Success!!!!!! ret = %d", ret);
+ }
+
+ // Test Code for get the plaintext ro
+ /*{
+ std::string tmpPath((char *)(t_RO.t_Content.CID));
+ tmpPath += ".ro";
+
+ FILE *fd = fopen(tmpPath.c_str(), "w+b");
+ if (fd == NULL)
+ {
+ goto Error_Exit;
+ }
+ fwrite(declicbuffer, 1, strlen(declicbuffer), fd);
+ fclose(fd);
+ DRM_TAPPS_LOG("Save decrypted RO success!, path = %s", tmpPath.c_str());
+ }*/
+ // Test Code Done!
+
+Error_Exit:
+ TADC_MEMFree_RO(&t_RO);
+
+ if (db_buffer_org)
+ {
+ DTAPPS_FREE((unsigned char*)db_buffer_org);
+ }
+ if (encr_cek)
+ {
+ DTAPPS_FREE(encr_cek);
+ }
+
+ return ret;
+}
+
+int DTappsHasValidLicense(const char* szCid)
+{
+ int len = 0, const_buf_enclen = 0, hash_buf_enclen = 0, const_buf_declen = 0, hash_buf_declen = 0;
+
+ unsigned char *pDevKey = NULL;
+ unsigned int DevKeyLen = 0;
+ unsigned char const_buffer_dec[512] = {0, };
+ unsigned char hash_buffer_dec[64] = {0, };
+ unsigned char md[64] = {0, };
+ unsigned int md_len = 0;
+
+ DTAPPS_RIGHTS_ROW row;
+ bool check = FALSE;
+
+ int check_valid = TADC_LICENSE_VALID;
+ DTAPPS_CONSTRAINTS st_constaints = {0, };
+
+ check = DTapps_RIGHTS_SELECT_ONE(szCid, &row);
+ if (check != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("There is no RO in the DB. cid = %s", szCid);
+ check_valid = TADC_LICENSE_NO_LICENSE;
+ goto DTAPPS_END;
+ }
+
+ if (0 == DTappsGetDeviceKey(&pDevKey, &DevKeyLen))
+ {
+ DRM_TAPPS_EXCEPTION("Error in DTAppsGetDeviceKey pDevKey = %s, DevKeyLen = %d", pDevKey, DevKeyLen);
+ check_valid = TADC_LICENSE_UNKNOWN_ERROR;
+ goto DTAPPS_END;
+ }
+
+ /* BASE64 Decode the constraints buffer extracted from the DB */
+ const_buf_enclen = TAPPS_STRLEN(row.constraint_buffer);
+ const_buf_declen = const_buf_enclen / 4 * 3;
+ if (const_buf_enclen <= 0)
+ {
+ DRM_TAPPS_EXCEPTION("There is no constaints buffer in the DB. cid = %s", szCid);
+ check_valid = TADC_LICENSE_UNKNOWN_ERROR;
+ goto DTAPPS_END;
+ }
+ DRM_TAPPS_FRQ_LOG("const_buf_enclen = %d, const_buf_declen = %d", const_buf_enclen, const_buf_declen);
+
+ (void)DTappsB64Decode((unsigned char*)row.constraint_buffer, const_buf_enclen, const_buffer_dec, const_buf_declen);
+ if (const_buf_declen > (const_buf_enclen / 4 * 3))
+ {
+ DRM_TAPPS_EXCEPTION("BASE64 Decode error !!! const_buffer_dec = %s, const_buf_declen = %d, (const_buf_enclen/4*3) = %d", const_buffer_dec, const_buf_declen, (const_buf_enclen / 4 * 3));
+ check_valid = TADC_LICENSE_UNKNOWN_ERROR;
+ goto DTAPPS_END;
+ }
+
+ /* BASE64 Decode the hash buffer extracted from the DB */
+ DTAPPS_MEMSET(hash_buffer_dec, 0x00, sizeof(hash_buffer_dec));
+ DTAPPS_MEMSET(md, 0x00, sizeof(md));
+
+ hash_buf_enclen = TAPPS_STRLEN(row.constraint_hash);
+ hash_buf_declen = hash_buf_enclen / 4 * 3;
+ if (hash_buf_enclen <= 0)
+ {
+ DRM_TAPPS_EXCEPTION("There is no constaints_hash buffer in the DB. cid = %s", szCid);
+ check_valid = TADC_LICENSE_UNKNOWN_ERROR;
+ goto DTAPPS_END;
+ }
+ DRM_TAPPS_FRQ_LOG("hash_buf_enclen = %d, hash_buf_declen = %d", hash_buf_enclen, hash_buf_declen);
+
+ (void)DTappsB64Decode((unsigned char*)row.constraint_hash, hash_buf_enclen, hash_buffer_dec, hash_buf_declen);
+ if (hash_buf_declen > (hash_buf_enclen / 4 * 3))
+ {
+ DRM_TAPPS_EXCEPTION("BASE64 Decode error !!! hash_buffer_dec = %s, hash_buf_declen = %d, (hash_buf_enclen/4*3) = %d", hash_buffer_dec, hash_buf_declen, (hash_buf_enclen / 4 * 3));
+ check_valid = TADC_LICENSE_UNKNOWN_ERROR;
+ goto DTAPPS_END;
+ }
+
+ /* Calculate the hash using HMAC from the BASE64Decoded Constraint Buffers and check with the BASE64Decoded Hash buffers */
+ DTappsCalHMACSHA1(pDevKey, (int)DevKeyLen, const_buffer_dec, const_buf_declen, md, &md_len);
+ if (DTAPPS_MEMCMP(md, hash_buffer_dec, hash_buf_declen) == 0)
+ {
+ DRM_TAPPS_LOG("HASH matching!!! md = %s, hash_buffer_dec = %s, hash_buf_declen = %d", md, hash_buffer_dec, hash_buf_declen);
+ }
+ else
+ {
+ DRM_TAPPS_EXCEPTION("HASH not matching!!! md = %s, hash_buffer_dec = %s, hash_buf_declen = %d", md, hash_buffer_dec, hash_buf_declen);
+ check_valid = TADC_LICENSE_UNKNOWN_ERROR;
+ goto DTAPPS_END;
+ }
+
+ /* Validate the constraints buffer */
+ DTAPPS_MEMCPY(&st_constaints, const_buffer_dec, sizeof(DTAPPS_CONSTRAINTS));
+
+ check_valid = DTappsValidateConstraints(&st_constaints, DTAPPS_VERIFY);
+ if (check_valid != TADC_LICENSE_VALID)
+ {
+ DRM_TAPPS_LOG("Invalid Constraints for constraints_buffer = %s check_valid = %d", const_buffer_dec, check_valid);
+ /* TODO: Implementation of Auto Deletion feature to delete the rights from the DB if the rights are expired!!!*/
+ goto DTAPPS_END;
+ }
+ else
+ {
+ DRM_TAPPS_LOG("Rights are Valid!!! Found atleast one Valid Rights..... return with Success!! check_valid = %d", check_valid);
+ }
+
+DTAPPS_END:
+ if (pDevKey)
+ {
+ DTappsFreeDeviceKey(&pDevKey);
+ }
+ if (check_valid != TADC_LICENSE_VALID)
+ {
+ DRM_TAPPS_EXCEPTION("Constraints not Valid!!!! check_valid = %d", check_valid);
+ DRM_TAPPS_EXCEPTION("DrmTdcHasValidLicense Failed!!!");
+ return check_valid;
+ }
+ else
+ {
+ DRM_TAPPS_LOG("Constraints are Valid!! check_valid = %d", check_valid);
+ return TADC_LICENSE_VALID;
+ }
+}
+
+int DTappsGetROInfo(const char* pszXML, T_RO *t_RO, unsigned char* name)
+{
+ int nResult = 0;
+ CXMLFile oXMLFile;
+ CXMLElement* pRoot, *pElement;
+ CPointerArray paChilds;
+ LPCTSTR pszValue;
+ int length = 0;
+ TADC_U8 TempVersion[3] = {0};
+ unsigned char *pbBuffer = NULL;
+ int len_enc = 0, len_dec = 0;
+
+ const char *pRoHeader = "<?xml version=\"1.0\"?>\n<TizenLicense>";
+
+ //Check Param Buffer
+ if (pszXML == NULL || t_RO == NULL || name == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("Parameters NULL!!! pszXML = %p, t_RO = %p", pszXML, t_RO);
+ return -1;
+ }
+
+ if (memcmp(pszXML, pRoHeader, strlen(pRoHeader))) {
+ DRM_TAPPS_EXCEPTION("TADC_IF_MemCmp. pRoHeader[%s] Error Code = %x", pRoHeader, TADC_XMLPARSER_ERROR);
+ return -1;
+ }
+
+ DTAPPS_MEMSET(t_RO, 0, sizeof(T_RO));
+
+ nResult = oXMLFile.LoadFromStream((LPCTSTR)pszXML);
+ if (nResult < 0)
+ {
+ DRM_TAPPS_EXCEPTION("oXMLFile.LoadFromStream is failed\n");
+ nResult = -1;
+ goto finish;
+ }
+
+ // Set Version
+ pRoot = oXMLFile.GetRoot();
+ if (pRoot == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("oXMLFile.GetRoot is failed\n");
+ nResult = -1;
+ goto finish;
+ }
+
+ // Get UID -> Name
+ pRoot = oXMLFile.GetRoot();
+ if (pRoot == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("oXMLFile.GetRoot is failed\n");
+ nResult = -1;
+ goto finish;
+ }
+
+ paChilds.RemoveAll();
+ nResult = pRoot->Find(&paChilds, _T("LicenseInfo"), _T("uid"), NULL);
+ if (nResult != 0)
+ {
+ DRM_TAPPS_EXCEPTION("pRoot->Find is failed\n");
+ nResult = -1;
+ goto finish;
+ }
+
+ if (paChilds.GetCount() != 1)
+ {
+ DRM_TAPPS_EXCEPTION("paChilds.GetCount() is failed\n");
+ nResult = -1;
+ goto finish;
+ }
+
+ pElement = (CXMLElement*) paChilds.Get(0);
+ pszValue = pElement->GetValue();
+ if (pszValue == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("pElement->GetValue() is failed\n");
+ nResult = -2;
+ goto finish;
+ }
+
+ length = TAPPS_STRLEN(pszValue);
+ if (length <= 0 || length > DTAPPS_NAME_SIZE)
+ {
+ DRM_TAPPS_EXCEPTION("TAPPS_STRLEN failed(%d) - %s\n", length, pszValue);
+ nResult = -1;
+ goto finish;
+ }
+
+ memcpy(name, pszValue, length + 1);
+ DRM_TAPPS_LOG("name = %s", name);
+
+ // Get UID -> CID
+ pRoot = oXMLFile.GetRoot();
+ if (pRoot == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("oXMLFile.GetRoot is failed\n");
+ nResult = -1;
+ goto finish;
+ }
+
+ paChilds.RemoveAll();
+ nResult = pRoot->Find(&paChilds, _T("ContentInfo"), _T("cid"), NULL);
+ if (nResult != 0)
+ {
+ DRM_TAPPS_EXCEPTION("pRoot->Find is failed\n");
+ nResult = -1;
+ goto finish;
+ }
+ if (paChilds.GetCount() != 1)
+ {
+ DRM_TAPPS_EXCEPTION("paChilds.GetCount() is failed\n");
+ nResult = -1;
+ goto finish;
+ }
+
+ pElement = (CXMLElement*)paChilds.Get(0);
+ pszValue = pElement->GetValue();
+ if (pszValue == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("pElement->GetValue() is failed\n");
+ nResult = -2;
+ goto finish;
+ }
+
+ length = TAPPS_STRLEN(pszValue);
+ if (length <= 0 || length > CID_SIZE)
+ {
+ DRM_TAPPS_EXCEPTION("TAPPS_STRLEN is failed(%d) - %s\n", length, pszValue);
+ nResult = -1;
+ goto finish;
+ }
+
+ t_RO->t_Content.CID = (TADC_U8*)DTAPPS_MALLOC(CID_SIZE + 1);
+ IF_TRUE_GOTO(t_RO->t_Content.CID == NULL, -2);
+
+ memset(t_RO->t_Content.CID, 0, CID_SIZE + 1);
+ memcpy(t_RO->t_Content.CID, pszValue, CID_SIZE + 1);
+
+ // Get KeyValue (CEK)
+ pRoot = oXMLFile.GetRoot();
+ IF_TRUE_GOTO(pRoot == NULL, ERROR_INVALID_DATA);
+ paChilds.RemoveAll();
+ nResult = pRoot->Find(&paChilds, _T("KeyInfo"), _T("CipherValue"), NULL);
+
+ IF_TRUE_GOTO( nResult != 0, ERROR_INVALID_DATA );
+ IF_TRUE_GOTO( paChilds.GetCount() != 1, ERROR_INVALID_DATA );
+
+ pElement = (CXMLElement*)paChilds.Get(0);
+ pszValue = pElement->GetValue();
+ IF_TRUE_GOTO(pszValue == NULL, -2);
+
+ len_enc = TAPPS_STRLEN(pszValue);
+ len_dec = len_enc / 4 * 3;
+
+ DRM_TAPPS_LOG("CEK raw = [%s], len_enc = [%d], len_dec = [%d]", pszValue, len_enc, len_dec);
+
+#if 0
+ pbBuffer = (unsigned char*)DTAPPS_MALLOC(len_dec + 1);
+ if (pbBuffer == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("Memory Allocation Error pbBuffer = %p", pbBuffer);
+ nResult = -2;
+ goto finish;
+ }
+
+ DTAPPS_MEMSET(pbBuffer, 0x00, len_dec + 1);
+#endif
+
+ pbBuffer = Base64Decode(pszValue, &len_dec);
+ if (pbBuffer == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("Memory Allocation Error pbBuffer = %p", pbBuffer);
+ nResult = -2;
+ goto finish;
+ }
+
+ if (len_dec > (len_enc / 4 * 3))
+ {
+ DRM_TAPPS_EXCEPTION("BASE64 Decode error !!! pbBuffer=%s, len_dec=%d, (len_enc/4*3)=%d", pbBuffer, len_dec, (len_enc / 4 * 3));
+ nResult = -1;
+ goto finish;
+ }
+ if (len_dec != CEK_SIZE)
+ {
+ DRM_TAPPS_EXCEPTION("BASE64 Decode error !!! CEK size=%d, len_dec=%d", CEK_SIZE, len_dec);
+ nResult = -1;
+ goto finish;
+ }
+
+ DRM_TAPPS_LOG("Base64Decoded CEK pbBuffer=%s, len_dec=%d, (len_enc/4*3)=%d", pbBuffer, len_dec, (len_enc / 4 * 3));
+
+ t_RO->t_Content.CEK = (TADC_U8*)DTAPPS_MALLOC(CEK_SIZE + 1);
+ IF_TRUE_GOTO(t_RO->t_Content.CEK == NULL, -2);
+ DTAPPS_MEMSET(t_RO->t_Content.CEK, 0x00, CEK_SIZE + 1);
+ DTAPPS_MEMCPY(t_RO->t_Content.CEK, pbBuffer, CEK_SIZE);
+ DRM_TAPPS_SECURE_LOG("CEK t_RO->t_Content.CEK = %s", t_RO->t_Content.CEK);
+
+ // Get individual
+ pRoot = oXMLFile.GetRoot();
+ IF_TRUE_GOTO( pRoot == NULL, ERROR_INVALID_DATA );
+
+ paChilds.RemoveAll();
+ nResult = pRoot->Find(&paChilds, _T("DeviceInfo"), _T("DUID"), NULL);
+
+ IF_TRUE_GOTO(nResult != 0, ERROR_INVALID_DATA);
+ IF_TRUE_GOTO(paChilds.GetCount() != 1, ERROR_INVALID_DATA);
+
+ pElement = (CXMLElement*)paChilds.Get(0);
+ pszValue = pElement->GetValue();
+ IF_TRUE_GOTO(pszValue == NULL, -1);
+ length = TADC_IF_StrLen((char*)pszValue);
+ if (length <= 0)
+ {
+ nResult = -1;
+ goto finish;
+ }
+
+ t_RO->PerFlag |= DUID_RULE;
+ t_RO->t_Permission.t_Individual.BindingType |= DUID_RULE;
+ t_RO->t_Permission.t_Individual.DUID = (TADC_U8*)TADC_IF_Malloc(length + 1);
+
+ if (t_RO->t_Permission.t_Individual.DUID == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("TADC_IF_MemCmp Error Code = %x", TADC_MEMAlOC_ERROR);
+ }
+
+ TADC_IF_MemSet(t_RO->t_Permission.t_Individual.DUID, 0, length + 1);
+ TADC_IF_MemCpy((CHAR*)t_RO->t_Permission.t_Individual.DUID, pszValue, length);
+
+ nResult = 0;
+
+finish:
+ pszValue = NULL;
+
+ if (pbBuffer)
+ {
+ DTAPPS_FREE(pbBuffer);
+ }
+
+ if (nResult < 0)
+ {
+ DRM_TAPPS_EXCEPTION(" Error Code = %x", TADC_XMLPARSER_ERROR);
+ }
+
+ if (nResult == -2)
+ {
+ DRM_TAPPS_EXCEPTION(" Error Code = %x", TADC_MEMAlOC_ERROR);
+ }
+
+ return nResult;
+}
+
+BOOL DTappsGetCEK(const char* szCid, T_RO* t_RO)
+{
+ char sql_query[2048] = {0, };
+ int db_buf_enclen = 0, hash_buf_enclen = 0, db_buf_declen = 0, hash_buf_declen = 0;
+ DTAPPS_RIGHTS_ROW row;
+ BOOL check = FALSE;
+
+ unsigned char const_buffer_dec[512] = {0, };
+ unsigned char encr_cek[128] = {0, };
+
+ unsigned char hash_buffer[64] = {0, };
+ unsigned char md[64] = {0, };
+ unsigned int md_len = 0;
+
+ unsigned char *pDevKey = NULL;
+ unsigned int DevKeyLen = 0;
+
+ int check_valid = TADC_LICENSE_VALID;
+ DTAPPS_CONSTRAINTS st_constaints = {0, };
+
+ AES_KEY key = {{0}};
+
+ if (NULL == szCid || NULL == t_RO)
+ {
+ DRM_TAPPS_EXCEPTION("Null Parameters!! szCid = %p, t_RO = %p", szCid, t_RO);
+ goto DTAPPS_ERROR;
+ }
+
+ check = DTapps_RIGHTS_SELECT_ONE(szCid, &row);
+ if (check != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("There is no RO in the DB. cid=%s", szCid);
+ check_valid = TADC_LICENSE_NO_LICENSE;
+ goto DTAPPS_ERROR;
+ }
+
+ if (0 == DTappsGetDeviceKey(&pDevKey, &DevKeyLen))
+ {
+ DRM_TAPPS_EXCEPTION("error in DTappsGetDeviceKey pDevKey = %s, DevKeyLen = %d", pDevKey, DevKeyLen);
+ check_valid = TADC_LICENSE_UNKNOWN_ERROR;
+ goto DTAPPS_ERROR;
+ }
+ DRM_TAPPS_LOG("DTappsGetDeviceKey pDevKey = %s, DevKeyLen = %d", pDevKey, DevKeyLen);
+
+ check_valid = TADC_LICENSE_VALID;
+
+ /* BASE64 Decode the constraints buffer extracted from the DB */
+ db_buf_enclen = TAPPS_STRLEN(row.constraint_buffer);
+ db_buf_declen = db_buf_enclen / 4 * 3;
+ if (db_buf_enclen <= 0)
+ {
+ DRM_TAPPS_EXCEPTION("There is no constaints buffer in the DB. cid = %s", szCid);
+ check_valid = TADC_LICENSE_UNKNOWN_ERROR;
+ goto DTAPPS_ERROR;
+ }
+
+ DRM_TAPPS_FRQ_LOG("db_buf_enclen = %d, db_buf_declen = %d", db_buf_enclen, db_buf_declen);
+
+ (void)DTappsB64Decode((unsigned char*)row.constraint_buffer, db_buf_enclen, const_buffer_dec, db_buf_declen);
+ if (db_buf_declen > (db_buf_enclen / 4 * 3))
+ {
+ DRM_TAPPS_EXCEPTION("BASE64 Decode error! const_buffer_dec=%s, db_buf_declen=%d, (db_buf_enclen/4*3)=%d", const_buffer_dec, db_buf_declen, (db_buf_enclen / 4 * 3));
+ check_valid = TADC_LICENSE_UNKNOWN_ERROR;
+ goto DTAPPS_ERROR;
+ }
+
+ /* BASE64 Decode the hash buffer extracted from the DB */
+ DTAPPS_MEMSET(hash_buffer, 0x00, sizeof(hash_buffer));
+ DTAPPS_MEMSET(md, 0x00, sizeof(md));
+
+ hash_buf_enclen = TAPPS_STRLEN(row.constraint_hash);
+ hash_buf_declen = hash_buf_enclen / 4 * 3;
+ if (hash_buf_enclen <= 0)
+ {
+ DRM_TAPPS_EXCEPTION("There is no hash buffer in the DB. cid = %s", szCid);
+ check_valid = TADC_LICENSE_UNKNOWN_ERROR;
+ goto DTAPPS_ERROR;
+ }
+ DRM_TAPPS_FRQ_LOG("hash_buf_enclen = %d, hash_buf_declen = %d", hash_buf_enclen, hash_buf_declen);
+
+ (void)DTappsB64Decode((unsigned char*)row.constraint_hash, hash_buf_enclen, hash_buffer, hash_buf_declen);
+ if (hash_buf_declen > (hash_buf_enclen / 4 * 3))
+ {
+ DRM_TAPPS_EXCEPTION("BASE64 Decode error! hash_buffer_dec=%s, hash_buf_declen=%d, (hash_buf_enclen/4*3)=%d", hash_buffer, hash_buf_declen, (hash_buf_enclen / 4 * 3));
+ check_valid = TADC_LICENSE_UNKNOWN_ERROR;
+ goto DTAPPS_ERROR;
+ }
+
+ /* Calculate the hash using HMAC from the BASE64Decoded Constraint Buffers and check with the BASE64Decoded Hash buffers */
+ DTappsCalHMACSHA1(pDevKey, (int)DevKeyLen, const_buffer_dec, db_buf_declen, md, &md_len);
+ if (DTAPPS_MEMCMP(md, hash_buffer, hash_buf_declen) == 0)
+ {
+ DRM_TAPPS_LOG("HASH for constraint buffer matching! md=%s, hash_buffer_dec=%s, hash_buf_declen=%d", md, hash_buffer, hash_buf_declen);
+ }
+ else
+ {
+ DRM_TAPPS_EXCEPTION("HASH for constraint buffer not matching! md=%s, hash_buffer_dec=%s, hash_buf_declen=%d", md, hash_buffer, hash_buf_declen);
+ check_valid = TADC_LICENSE_UNKNOWN_ERROR;
+ goto DTAPPS_ERROR;
+ }
+
+ /* Validate the constraints buffer */
+ DTAPPS_MEMCPY(&st_constaints, const_buffer_dec, sizeof(DTAPPS_CONSTRAINTS));
+
+ check_valid = DTappsValidateConstraints(&st_constaints, DTAPPS_VERIFY);
+ if (check_valid != TADC_LICENSE_VALID)
+ {
+ DRM_TAPPS_LOG("Invalid Constraints for constraints_buffer=%s, check_valid=%d", const_buffer_dec, check_valid);
+ /* TODO: Implementation of Auto Deletion feature to delete the rights from the DB if the rights are expired!!!*/
+ goto DTAPPS_ERROR;
+ }
+ else
+ {
+ DRM_TAPPS_LOG("Rights are Valid! check_valid = %d", check_valid);
+
+ /* Constraints valid - Extract CEK and fill the t_RO structure with CEK, DUID */
+ /* BASE64 Decode the CEK buffer extracted from the DB */
+ db_buf_enclen = TAPPS_STRLEN(row.cek);
+ db_buf_declen = db_buf_enclen / 4 * 3;
+ if (db_buf_enclen <= 0)
+ {
+ DRM_TAPPS_EXCEPTION("There is no CEK in the DB. cid = %s", szCid);
+ check_valid = TADC_LICENSE_UNKNOWN_ERROR;
+ goto DTAPPS_ERROR;
+ }
+ DRM_TAPPS_FRQ_LOG("db_buf_enclen = %d, db_buf_declen = %d", db_buf_enclen, db_buf_declen);
+
+ int cek_declen = 0;
+
+ (void)DTappsB64Decode((unsigned char*)row.cek, db_buf_enclen, encr_cek, cek_declen);
+ db_buf_declen = cek_declen;
+
+ if (cek_declen > (db_buf_enclen / 4 * 3))
+ {
+ DRM_TAPPS_EXCEPTION("BASE64 Decode error! encr_cek=%s, cek_declen=%d, (db_buf_enclen/4*3)=%d", encr_cek, cek_declen, (db_buf_enclen / 4 * 3));
+ check_valid = TADC_LICENSE_UNKNOWN_ERROR;
+ goto DTAPPS_ERROR;
+ }
+ DRM_TAPPS_LOG("BASE64 encr_cek=%s, cek_declen=%d, db_buf_declen=%d, (db_buf_enclen/4*3)=%d", encr_cek, cek_declen, db_buf_declen, (db_buf_enclen / 4 * 3));
+
+ /* BASE64 Decode the hash buffer extracted from the DB */
+ DTAPPS_MEMSET(hash_buffer, 0x00, sizeof(hash_buffer));
+ DTAPPS_MEMSET(md, 0x00, sizeof(md));
+
+ hash_buf_enclen = TAPPS_STRLEN(row.cek_hash);
+ hash_buf_declen = hash_buf_enclen / 4 * 3;
+ if (db_buf_enclen <= 0)
+ {
+ DRM_TAPPS_EXCEPTION("There is no CEK_hash buffer in the DB. cid = %s", szCid);
+ check_valid = TADC_LICENSE_UNKNOWN_ERROR;
+ goto DTAPPS_ERROR;
+ }
+ DRM_TAPPS_FRQ_LOG("hash_buf_enclen = %d, hash_buf_declen = %d", hash_buf_enclen, hash_buf_declen);
+
+ (void)DTappsB64Decode((unsigned char*)row.cek_hash, hash_buf_enclen, hash_buffer, hash_buf_declen);
+ if (hash_buf_declen > (hash_buf_enclen / 4 * 3))
+ {
+ DRM_TAPPS_EXCEPTION("BASE64 Decode error! hash_buffer_dec=%s, hash_buf_declen=%d, (hash_buf_enclen/4*3)=%d", hash_buffer, hash_buf_declen, (hash_buf_enclen/4*3));
+ check_valid = TADC_LICENSE_UNKNOWN_ERROR;
+ goto DTAPPS_ERROR;
+ }
+
+ /* Calculate the hash using HMAC from the BASE64Decoded Encrypted CEK Buffer and check with the BASE64Decoded Hash buffer */
+ DTappsCalHMACSHA1(pDevKey, (int)DevKeyLen, encr_cek, db_buf_declen, md, &md_len);
+ if (DTAPPS_MEMCMP(md, hash_buffer, hash_buf_declen) == 0)
+ {
+ DRM_TAPPS_LOG("HASH for Encrypted CEK buffer matching! md=%s, hash_buffer_dec=%s, hash_buf_declen=%d", md, hash_buffer, hash_buf_declen);
+ }
+ else
+ {
+ DRM_TAPPS_EXCEPTION("HASH for Encrypted CEK buffer not matching! md=%s, hash_buffer_dec=%s, hash_buf_declen=%d", md, hash_buffer, hash_buf_declen);
+ check_valid = TADC_LICENSE_UNKNOWN_ERROR;
+ goto DTAPPS_ERROR;
+ }
+
+ /* Allocate memory for CEK */
+ t_RO->t_Content.CEK = (unsigned char*)DTAPPS_MALLOC(CEK_SIZE + 1);
+ if (NULL == t_RO->t_Content.CEK)
+ {
+ DRM_TAPPS_EXCEPTION("Memory Allocation Error!! t_RO->t_Content.CEK = %p", t_RO->t_Content.CEK);
+ check_valid = TADC_LICENSE_UNKNOWN_ERROR;
+ goto DTAPPS_ERROR;
+ }
+
+ DTAPPS_MEMSET(t_RO->t_Content.CEK, 0x00, CEK_SIZE + 1);
+ /* Decrypt CEK and update t_RO structure */
+ if (DTAPPS_AES_SET_DECR_KEY(pDevKey, 128, &key))
+ {
+ DRM_TAPPS_EXCEPTION("AES_set_decrypt_key failed!!");
+ check_valid = TADC_LICENSE_UNKNOWN_ERROR;
+ goto DTAPPS_ERROR;
+ }
+
+ (void)DTAPPS_AES_UNWRAP_KEY(&key, NULL, t_RO->t_Content.CEK, encr_cek, cek_declen);
+ DRM_TAPPS_LOG("DTAPPS_AES_UNWRAP_KEY success!!");
+
+ /* Store DUID in t_RO */
+ if (st_constaints.DUID[0] != '\0')
+ {
+ t_RO -> t_Permission.t_Individual.DUID = (unsigned char*)DTAPPS_MALLOC(DUID_SIZE + 1);
+ if (NULL == t_RO -> t_Permission.t_Individual.DUID)
+ {
+ DRM_TAPPS_EXCEPTION("Memory Allocation Error!! t_RO->t_Permission.t_Individual.DUID = %p", t_RO -> t_Permission.t_Individual.DUID);
+ check_valid = TADC_LICENSE_UNKNOWN_ERROR;
+ goto DTAPPS_ERROR;
+ }
+ DTAPPS_MEMSET(t_RO -> t_Permission.t_Individual.DUID, 0x00, DUID_SIZE + 1);
+ t_RO->PerFlag |= DUID_RULE;
+ t_RO->t_Permission.t_Individual.BindingType |= DUID_RULE;
+ DTAPPS_MEMCPY(t_RO -> t_Permission.t_Individual.DUID, st_constaints.DUID, DUID_SIZE);
+ }
+ }
+
+DTAPPS_ERROR:
+ if (pDevKey)
+ {
+ DTappsFreeDeviceKey(&pDevKey);
+ }
+
+ if (check_valid != TADC_LICENSE_VALID)
+ {
+ DRM_TAPPS_EXCEPTION("DTappsGetCEK FAILED!!!, check_valid = %d", check_valid);
+ return FALSE;
+ }
+ else
+ {
+ /* All fine... Allocate memory for CID and fill the value */
+ if ((t_RO != NULL) && (szCid != NULL))
+ {
+ t_RO -> t_Content.CID = (unsigned char*) DTAPPS_MALLOC(CID_SIZE + 1);
+ if (NULL == t_RO -> t_Content.CID)
+ {
+ DRM_TAPPS_EXCEPTION("Memory Allocation Error!! t_RO->t_Content.CID = %p", t_RO -> t_Content.CID);
+ check_valid = TADC_LICENSE_UNKNOWN_ERROR;
+ goto DTAPPS_ERROR;
+ }
+ DTAPPS_MEMSET(t_RO -> t_Content.CID, 0x00, CID_SIZE + 1);
+ DTAPPS_MEMCPY(t_RO -> t_Content.CID, szCid, CID_SIZE);
+ DRM_TAPPS_LOG("DTappsGetCEK SUCCESS!!!, check_valid = %d", check_valid);
+ }
+
+ return TRUE;
+ }
+}
+
+BOOL DTapps_RIGHTS_INSTALL(const char* name,
+ const char* time,
+ #ifdef DTAPPS_STORE_CEK_IN_DB
+ const char* cek,
+ const char* cek_hash,
+ #endif
+ const char* constraint_buffer,
+ const char* constraint_hash,
+ const char* cid,
+ BOOL isUpdate)
+{
+ void* pDb = NULL;
+ const char* query = NULL;
+ sqlite3_stmt* pstmt = NULL;
+ unsigned int dIdx = 0;
+ BOOL ret_value = FALSE;
+
+ DRM_TAPPS_LOG("Open DB......");
+ ret_value = DTappsDBOpen(pDb,__func__);
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("DB Open Failed!! ret_value = %d",ret_value);
+ return FALSE;
+ }
+
+ if(isUpdate == FALSE)
+ {
+ query = "INSERT INTO dtapps2rights (name, time_t, "
+ #ifdef DTAPPS_STORE_CEK_IN_DB
+ " cek, cek_hash, "
+ #endif
+ " constraint_buffer, constraint_hash, cid) "
+ " VALUES (?, ?, "
+ #ifdef DTAPPS_STORE_CEK_IN_DB
+ " ?, ?, "
+ #endif
+ " ?, ?, ?);";
+ }
+ else
+ {
+ query = "UPDATE dtapps2rights SET name=?, time_t=?,"
+ #ifdef DTAPPS_STORE_CEK_IN_DB
+ " cek=?, cek_hash=?, "
+ #endif
+ " constraint_buffer=?, constraint_hash=? "
+ " WHERE r_id=?;";
+ }
+
+ DRM_TAPPS_LOG("Prepare Statement........");
+ pstmt = (sqlite3_stmt*) DTappsStmtPrepare(pDb, query);
+ if(pstmt == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("Prepare Statement failed. query=%s", query);
+ goto Error_Exit;
+ }
+
+ DRM_TAPPS_LOG("Binding Parameters........");
+ ret_value = DTappsStmtBindParam(pstmt, dIdx++, TAPPSDB_TYPE_VARCHAR, (void *)name, strlen(name));
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("Binding Parameter(name=%s) failed. ret_value = %d", name, ret_value);
+ goto Error_Exit;
+ }
+
+ ret_value = DTappsStmtBindParam(pstmt, dIdx++, TAPPSDB_TYPE_VARCHAR, (void *)time, strlen(time));
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("Binding Parameter(time=%s) failed. ret_value = %d", time, ret_value);
+ goto Error_Exit;
+ }
+
+ #ifdef DTAPPS_STORE_CEK_IN_DB
+ ret_value = DTappsStmtBindParam(pstmt, dIdx++, TAPPSDB_TYPE_VARCHAR, (void *)cek, strlen(cek));
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("Binding Parameter(cek=%s) failed. ret_value = %d", cek, ret_value);
+ goto Error_Exit;
+ }
+
+ ret_value = DTappsStmtBindParam(pstmt, dIdx++, TAPPSDB_TYPE_VARCHAR, (void *)cek_hash, strlen(cek_hash));
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("Binding Parameter(cek_hash=%s) failed. ret_value = %d", cek_hash, ret_value);
+ goto Error_Exit;
+ }
+ #endif
+
+ ret_value = DTappsStmtBindParam(pstmt, dIdx++, TAPPSDB_TYPE_VARCHAR, (void *)constraint_buffer, strlen(constraint_buffer));
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("Binding Parameter(constraint_buffer=%s) failed. ret_value = %d", constraint_buffer, ret_value);
+ goto Error_Exit;
+ }
+
+ ret_value = DTappsStmtBindParam(pstmt, dIdx++, TAPPSDB_TYPE_VARCHAR, (void *)constraint_hash, strlen(constraint_hash));
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("Binding Parameter(constraint_hash=%s) failed. ret_value = %d", constraint_hash, ret_value);
+ goto Error_Exit;
+ }
+
+ ret_value = DTappsStmtBindParam(pstmt, dIdx++, TAPPSDB_TYPE_VARCHAR, (void *)cid, strlen(cid));
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("Binding Parameter(cid=%s) failed. ret_value = %d", cid, ret_value);
+ goto Error_Exit;
+ }
+
+ DRM_TAPPS_LOG("Begin Transaction........");
+ ret_value = DTappsDBBeginImmedTrans(__func__);
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("DB Begin Transaction ret_value = %d",ret_value);
+ goto Error_Exit;
+ }
+
+ DRM_TAPPS_LOG("Execute SQL to Insert Contents into Table........");
+ ret_value = DTappsStmtExecute(pstmt);
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("Execute SQL Query Failed!! ret_value = %d",ret_value);
+ goto Error_Exit;
+ }
+
+ DRM_TAPPS_LOG("Commit DB........");
+ ret_value = DTappsDBCommit(__func__);
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("Commit DB Failed!! ret_value = %d",ret_value);
+ goto Error_Exit;
+ }
+
+ DRM_TAPPS_LOG("Release Statement........");
+ ret_value = DTappsStmtRelease(pstmt);
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("Release Statement Failed!! ret_value = %d",ret_value);
+ pstmt = NULL;
+ goto Error_Exit;
+ }
+
+ DRM_TAPPS_LOG("Close DB........");
+ ret_value = DTappsDBClose(__func__);
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("Close DB Failed!! ret_value = %d",ret_value);
+ goto Error_Exit;
+ }
+
+ DRM_TAPPS_LOG("Install DB Operartion Successful!!!");
+ return TRUE;
+
+Error_Exit:
+ if(pstmt != NULL)
+ DTappsStmtRelease(pstmt);
+
+ ret_value = DTappsDBRollback (__func__);
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("Rollback DB Failed!! ret_value = %d",ret_value);
+ }
+
+ ret_value = DTappsDBClose(__func__);
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("Close DB Failed!! ret_value = %d",ret_value);
+ }
+
+ return FALSE;
+}
+
+BOOL DTapps_RIGHTS_SELECT_ONE(const char* cid, DTAPPS_RIGHTS_ROW* row)
+{
+ void* pDb = NULL;
+ const char* query = NULL;
+ sqlite3_stmt* pstmt = NULL;
+ unsigned int dIdx = 0;
+ BOOL ret_value = FALSE;
+ int db_ret = -1;
+ DTAPPS_RIGHTS_ROW* result = row;
+
+ char *name, *time, *constraint_buffer, *constraint_hash;
+ #ifdef DTAPPS_STORE_CEK_IN_DB
+ char *cek, *cek_hash;
+ #endif
+
+ DRM_TAPPS_LOG("Open DB......");
+ ret_value = DTappsDBOpen(pDb,__func__);
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("DB Open Failed!! ret_value = %d",ret_value);
+ return FALSE;
+ }
+
+ query = "SELECT r_id, name, time_t, "
+ #ifdef DTAPPS_STORE_CEK_IN_DB
+ " cek, cek_hash, "
+ #endif
+ " constraint_buffer, constraint_hash "
+ " FROM dtapps2rights"
+ " WHERE cid=? ORDER BY r_id desc limit 1;";
+
+
+ DRM_TAPPS_LOG("Begin Transaction........");
+ ret_value = DTappsDBBeginImmedTrans(__func__);
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("DB Begin Transaction Failed!! ret_value = %d",ret_value);
+ goto Error_Exit;
+ }
+
+ DRM_TAPPS_LOG("Prepare Statement........");
+ db_ret = sqlite3_prepare((sqlite3*)pDb, query, -1, &pstmt, NULL);
+ if(pstmt == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("Prepare Statement failed. query=%s, error=%s", query, sqlite3_errmsg((sqlite3*)pDb));
+ goto Error_Exit;
+ }
+
+ DRM_TAPPS_LOG("Binding Parameters........");
+ db_ret = sqlite3_bind_text(pstmt, ++dIdx, cid, strlen(cid), SQLITE_TRANSIENT);
+ if(db_ret != SQLITE_OK)
+ {
+ DRM_TAPPS_EXCEPTION("Binding Parameter(cid=%s) failed. ret_value = %d, query=%s", cid, db_ret, query);
+ goto Error_Exit;
+ }
+
+ DRM_TAPPS_LOG("Execute SQL to Select Contents from Table........");
+ db_ret = sqlite3_step(pstmt);
+ if(db_ret == SQLITE_OK || db_ret == SQLITE_DONE)
+ {
+ DRM_TAPPS_FRQ_LOG("Executed SQL Select Query. But no row was returned");
+ goto Error_Exit;
+ }
+ else if(db_ret != SQLITE_ROW)
+ {
+ DRM_TAPPS_EXCEPTION("Execute SQL Query Failed!! ret_value = %d, query=%s, error=%s",
+ db_ret, query, sqlite3_errmsg((sqlite3*)pDb));
+ goto Error_Exit;
+ }
+
+ memset(result, 0, sizeof(DTAPPS_RIGHTS_ROW));
+
+ dIdx = 0;
+ result->r_id = sqlite3_column_int(pstmt, dIdx++);
+ DRM_TAPPS_LOG("....SEELECTED : r_id = %d", result->r_id);
+
+ name = (char*) sqlite3_column_text(pstmt, dIdx++);
+ if(name != NULL)
+ memcpy(result->name, name, strlen(name));
+ DRM_TAPPS_LOG("....SEELECTED : name = %s", result->name);
+
+ time= (char*) sqlite3_column_text(pstmt, dIdx++);
+ if(time != NULL)
+ memcpy(result->time, time, strlen(time));
+ DRM_TAPPS_LOG("....SEELECTED : time = %s", result->time);
+
+ #ifdef DTAPPS_STORE_CEK_IN_DB
+ cek= (char*) sqlite3_column_text(pstmt, dIdx++);
+ if(cek != NULL)
+ memcpy(result->cek, cek, strlen(cek));
+ DRM_TAPPS_LOG("....SEELECTED : cek = %s", result->cek);
+
+ cek_hash= (char*) sqlite3_column_text(pstmt, dIdx++);
+ if(cek_hash != NULL)
+ memcpy(result->cek_hash, cek_hash, strlen(cek_hash));
+ DRM_TAPPS_LOG("....SEELECTED : cek_hash = %s", result->cek_hash);
+ #endif
+
+ constraint_buffer = (char*) sqlite3_column_text(pstmt, dIdx++);
+ if(constraint_buffer != NULL)
+ memcpy(result->constraint_buffer, constraint_buffer, strlen(constraint_buffer));
+ DRM_TAPPS_LOG("....SEELECTED : constraint_buffer = %s", result->constraint_buffer);
+
+ constraint_hash = (char*) sqlite3_column_text(pstmt, dIdx++);
+ if(constraint_hash != NULL)
+ memcpy(result->constraint_hash, constraint_hash, strlen(constraint_hash));
+ DRM_TAPPS_LOG("....SEELECTED : constraint_hash = %s", result->constraint_hash);
+
+ memcpy(result->cid, cid, strlen(cid));
+ DRM_TAPPS_LOG("....SEELECTED : cid = %s", result->cid);
+
+ DRM_TAPPS_LOG("Release Statement........");
+ ret_value = DTappsStmtRelease(pstmt);
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("Release Statement Failed!! ret_value = %d",ret_value);
+ pstmt = NULL;
+ goto Error_Exit;
+ }
+
+ DRM_TAPPS_LOG("Close DB........");
+ ret_value = DTappsDBClose(__func__);
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("Close DB Failed!! ret_value = %d",ret_value);
+ goto Error_Exit;
+ }
+
+ DRM_TAPPS_LOG("Select a DB row Operartion Successful!!!");
+ return TRUE;
+
+Error_Exit:
+ if(pstmt)
+ DTappsStmtRelease(pstmt);
+
+ ret_value = DTappsDBClose(__func__);
+ if(ret_value != TRUE)
+ {
+ DRM_TAPPS_EXCEPTION("Close DB Failed!! ret_value = %d",ret_value);
+ }
+
+ return FALSE;
+}
diff --git a/tappsd/src/util/DTapps2Base64.cpp b/tappsd/src/util/DTapps2Base64.cpp
new file mode 100644
index 0000000..e7800ae
--- /dev/null
+++ b/tappsd/src/util/DTapps2Base64.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 DTapps2Base64.cpp
+ * @brief This file includes functions relating to Base64 Encode Decode.
+ */
+
+#include "DTapps2Base64.h"
+
+const unsigned char MAP[128] =
+{
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
+ 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
+ 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
+};
+
+const char CODE[64] =
+{
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+ 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3',
+ '4', '5', '6', '7', '8', '9', '+', '/'
+};
+
+BOOL DTappsB64Encode(unsigned char* in, int in_size, unsigned char* out, int out_size)
+{
+ int i, j;
+ unsigned char a, b, c;
+ int len = (in_size + 2) / 3 * 4;
+
+ if( out_size < len )
+ return FALSE;
+
+ for( i = 0, j = 0; j < len; i += 3, j += 4 )
+ {
+ a = b = c = 0;
+ a = *(in+i);
+ *(out+j) = CODE[(a >> 2) & 0x3F];
+ if( in_size - i > 2 )
+ {
+ b = *(in+i+1);
+ c = *(in+i+2);
+ *(out+j+1) = CODE[((a << 4) & 0x30) + ((b >> 4) & 0xf)];
+ *(out+j+2) = CODE[((b << 2) & 0x3c) + ((c >> 6) & 0x3)];
+ *(out+j+3) = CODE[c & 0x3F];
+ }
+ else if( in_size - i > 1 )
+ {
+ b = *(in+i+1);
+ *(out+j+1) = CODE[((a << 4) & 0x30) + ((b >> 4) & 0xf)];
+ *(out+j+2) = CODE[((b << 2) & 0x3c) + ((c >> 6) & 0x3)];
+ *(out+j+3) = '=';
+ }
+ else
+ {
+ *(out+j+1) = CODE[((a << 4) & 0x30) + ((b >> 4) & 0xf)];
+ *(out+j+2) = '=';
+ *(out+j+3) = '=';
+ }
+ }
+
+ return TRUE;
+}
+
+
+int DTappsB64Decode(unsigned char* in, int in_size, unsigned char* out, int& out_size)
+{
+ int i, j, k;
+ unsigned char c[4];
+ int read = 0;
+
+ for( i=j=k=0; i < in_size; i++ )
+ {
+ if( in[i] > 128 )
+ continue;
+ c[j] = MAP[(unsigned char)in[i]];
+ if( c[j] == 64 )
+ continue;
+ j++;
+
+ switch( j )
+ {
+ case 2:
+ out[k++] = (c[0]<<2) | ((c[1]>>4) & 0x3);
+ break;
+
+ case 3:
+ out[k++] = ((c[1]<<4) & 0xf0) | ((c[2]>>2) & 0xf);
+ break;
+
+ case 4:
+ out[k++] = ((c[2]<<6) & 0xc0) | c[3];
+ read = i;
+ j = 0;
+ break;
+ }
+ }
+
+ out_size = k;
+
+ return read+1;
+}
diff --git a/tappsd/src/util/DTapps2HMAC.cpp b/tappsd/src/util/DTapps2HMAC.cpp
new file mode 100644
index 0000000..9848de5
--- /dev/null
+++ b/tappsd/src/util/DTapps2HMAC.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 DTapps2HMAC.cpp
+ * @brief This file includes functions relating to HMAC.
+ * @author Harsha Shekar (h.shekar@samsung.com)
+ */
+#include <dukgen.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+
+#include "DTapps2HMAC.h"
+
+void DTappsCalHMACSHA1(unsigned char* key,int key_len,unsigned char* msg,size_t msglen,unsigned char *md,unsigned int *md_len)
+{
+ HMAC(EVP_sha1(),(void*)key,key_len,msg,msglen,md,md_len);
+}
+
+int DTappsGetDeviceKey(unsigned char **pDevKey,unsigned int *DevKeyLen)
+{
+ int ret = 0;
+ char passwd[30] = {0,};
+ unsigned int LocalKeyLen = 16;
+
+ char* pDuk = GetDeviceUniqueKey(passwd, strlen(passwd), 16);
+
+ if (!pDuk || !pDevKey || !DevKeyLen)
+ {
+ DRM_TAPPS_EXCEPTION("pDevKey = %p, DevKeyLen = %p",pDevKey,DevKeyLen);
+ goto DTApps_ERR;
+ }
+
+ DRM_TAPPS_LOG("LocalKeyLen = %u", LocalKeyLen);
+
+ *pDevKey = (unsigned char*)DTAPPS_MALLOC(LocalKeyLen + 1);
+
+ if(NULL == *pDevKey)
+ {
+ DRM_TAPPS_EXCEPTION("Malloc Failed");
+
+ goto DTApps_ERR;
+ }
+
+ DTAPPS_MEMSET(*pDevKey, 0x0, LocalKeyLen + 1);
+ DTAPPS_MEMCPY(*pDevKey, pDuk, LocalKeyLen);
+
+ *DevKeyLen = LocalKeyLen;
+ ret = 1;
+
+DTApps_ERR:
+
+ if (ret == 1)
+ DRM_TAPPS_LOG("SUCCESS:ret=%d", ret);
+ else
+ DRM_TAPPS_EXCEPTION("FAILED:ret=%d", ret);
+
+ free(pDuk);
+
+ return ret;
+}
+
+void DTappsFreeDeviceKey(unsigned char **pDevKey)
+{
+ if(pDevKey == NULL)
+ {
+ DRM_TAPPS_EXCEPTION("pDevKey = %p", pDevKey);
+
+ return;
+ }
+
+ DTAPPS_FREE(*pDevKey);
+ *pDevKey = NULL;
+}
diff --git a/tappsd/src/util/DTapps2Time.cpp b/tappsd/src/util/DTapps2Time.cpp
new file mode 100644
index 0000000..6157e9e
--- /dev/null
+++ b/tappsd/src/util/DTapps2Time.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 DTapps2Time.cpp
+ * @brief This file includes functions relating to TIME APIs.
+ */
+
+#include "DTapps2Time.h"
+
+ BOOL DTappsDtTmStr2Sec(unsigned char *time_str,time_t *TotalSec)
+ {
+ char str[32] = {0};
+ char short_str[5] = {0};
+ struct tm time_fmt = {0,};
+
+ (void)TAPPS_GSTRLCPY(str, (const char*)time_str, sizeof(str));
+
+ DRM_TAPPS_LOG("str = %s",str);
+
+ if(str[4] != '-' || str[7] != '-' || str[10] != 'T' || str[13] != ':' || str[16] != ':')
+ {
+ DRM_TAPPS_EXCEPTION("Format is incorrect:str=%s", str);
+
+ return FALSE;
+ }
+
+ DTAPPS_MEMCPY(short_str, str, 4);
+ time_fmt.tm_year = DTAPPS_ATOI(short_str) - 1900;
+ DRM_TAPPS_FRQ_LOG("tm_year = %d", time_fmt.tm_year);
+
+ DTAPPS_MEMSET(short_str, 0x0,5);
+ DTAPPS_MEMCPY(short_str, str + 5, 2);
+ time_fmt.tm_mon = DTAPPS_ATOI(short_str) - 1;
+ DRM_TAPPS_FRQ_LOG("tm_mon = %d", time_fmt.tm_mon);
+
+ DTAPPS_MEMCPY(short_str, str + 8, 2);
+ time_fmt.tm_mday = DTAPPS_ATOI(short_str);
+ DRM_TAPPS_FRQ_LOG("tm_mday = %d", time_fmt.tm_mday);
+
+ DTAPPS_MEMCPY(short_str, str + 11, 2);
+ time_fmt.tm_hour = DTAPPS_ATOI(short_str);
+ DRM_TAPPS_FRQ_LOG("tm_hour = %d", time_fmt.tm_hour);
+
+ DTAPPS_MEMCPY(short_str, str + 14, 2);
+ time_fmt.tm_min = DTAPPS_ATOI(short_str);
+ DRM_TAPPS_FRQ_LOG("tm_min = %d", time_fmt.tm_min);
+
+ DTAPPS_MEMCPY(short_str, str + 17, 2);
+ time_fmt.tm_sec = DTAPPS_ATOI(short_str);
+ DRM_TAPPS_FRQ_LOG("tm_sec = %d", time_fmt.tm_sec);
+
+ /* Convert into Seconds */
+ *TotalSec = DTAPPS_MKTIME(&time_fmt);
+ DRM_TAPPS_LOG("TotalSec = %lu", *TotalSec);
+
+ return TRUE;
+ }
+
+BOOL DTappsDtTmStr2StrucTm(unsigned char *time_str,struct tm *time_fmt)
+ {
+ char str[32] = {0};
+ char short_str[5] = {0};
+
+ (void)TAPPS_GSTRLCPY(str, (const char*)time_str, sizeof(str));
+
+ DRM_TAPPS_LOG("str = %s", str);
+
+ if(str[4]!='-' || str[7]!='-' || str[10]!='T' || str[13]!=':' || str[16]!=':')
+ {
+ DRM_TAPPS_EXCEPTION("Format is incorrect:str=%s", str);
+
+ return FALSE;
+ }
+
+ DTAPPS_MEMCPY(short_str, str, 4);
+ time_fmt->tm_year = DTAPPS_ATOI(short_str) - 1900;
+ DRM_TAPPS_FRQ_LOG("tm_year = %d", time_fmt->tm_year);
+
+ DTAPPS_MEMSET(short_str, 0x0, 5);
+ DTAPPS_MEMCPY(short_str, str + 5, 2);
+ time_fmt->tm_mon = DTAPPS_ATOI(short_str) - 1;
+ DRM_TAPPS_FRQ_LOG("tm_mon = %d", time_fmt->tm_mon);
+
+ DTAPPS_MEMCPY(short_str, str + 8, 2);
+ time_fmt->tm_mday = DTAPPS_ATOI(short_str);
+ DRM_TAPPS_FRQ_LOG("tm_mday = %d", time_fmt->tm_mday);
+
+ DTAPPS_MEMCPY(short_str, str + 11, 2);
+ time_fmt->tm_hour = DTAPPS_ATOI(short_str);
+ DRM_TAPPS_FRQ_LOG("tm_hour = %d", time_fmt->tm_hour);
+
+ DTAPPS_MEMCPY(short_str, str + 14, 2);
+ time_fmt->tm_min = DTAPPS_ATOI(short_str);
+ DRM_TAPPS_FRQ_LOG("tm_min = %d", time_fmt->tm_min);
+
+ DTAPPS_MEMCPY(short_str, str + 17, 2);
+ time_fmt->tm_sec = DTAPPS_ATOI(short_str);
+ DRM_TAPPS_FRQ_LOG("tm_sec = %d", time_fmt->tm_sec);
+
+ return TRUE;
+ }
+
+BOOL DTappsGetSecureTime(time_t* seconds)
+{
+ time_t now = 0, secure_sec = 0;
+ int Delta = 0;
+ struct tm gm_fmt;
+
+ now = DTAPPS_TIME(NULL);
+
+ /* TODO: Read the Delta from VCONF */
+
+ secure_sec = now + Delta;
+
+ /* Operations to be done in GMT - Convert this to GM Time */
+ DTAPPS_GMTIME_THREAD_SAFE(&secure_sec, &gm_fmt);
+ *seconds = DTAPPS_MKTIME(&gm_fmt);
+
+ DRM_TAPPS_LOG("now = %d, secure_sec = %d, seconds(SecureTime in GMT) = %d", now, secure_sec, *seconds);
+
+ return TRUE;
+}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
new file mode 100644
index 0000000..4e44c2c
--- /dev/null
+++ b/test/CMakeLists.txt
@@ -0,0 +1,118 @@
+pkg_check_modules(DRM_TEST_DEP
+ REQUIRED
+ dlog
+ db-util
+ openssl
+ dukgenerator
+ cryptsvc
+ libtzplatform-config
+)
+
+SET(DRMTESTUTIL_SRCS
+ ${PROJECT_SOURCE_DIR}/test/drm_testapps.cpp
+ ${PROJECT_SOURCE_DIR}/test/drm_testutil.cpp
+ ${PROJECT_SOURCE_DIR}/tadcore/TADCCore/TADC_Core.cpp
+ ${PROJECT_SOURCE_DIR}/tadcore/TADCCore/TADC_Sub.cpp
+ ${PROJECT_SOURCE_DIR}/tadcore/TADCCore/TADC_Util.cpp
+ ${PROJECT_SOURCE_DIR}/tadcore/TADCInterface/TADC_IF.cpp
+ ${PROJECT_SOURCE_DIR}/tadcore/Svc/DrmTdcSvc.cpp
+ ${PROJECT_SOURCE_DIR}/tappsd/src/intf/drm_intf_tapps.cpp
+ ${PROJECT_SOURCE_DIR}/tadcore/XMLParser/CPointerArray.cpp
+ ${PROJECT_SOURCE_DIR}/tadcore/XMLParser/CXMLAttribute.cpp
+ ${PROJECT_SOURCE_DIR}/tadcore/XMLParser/CXMLElement.cpp
+ ${PROJECT_SOURCE_DIR}/tadcore/XMLParser/CXMLFile.cpp
+ ${PROJECT_SOURCE_DIR}/tadcore/DrmFileHandleMgr/DrmFileApi.cpp
+ ${PROJECT_SOURCE_DIR}/tadcore/DrmFileHandleMgr/DrmFileHandler.cpp
+ ${PROJECT_SOURCE_DIR}/tadcore/DrmFileHandleMgr/DrmFileMgr.cpp
+ ${PROJECT_SOURCE_DIR}/tappsd/src/rights/DTapps2Rights.cpp
+ ${PROJECT_SOURCE_DIR}/tappsd/src/db/DTapps2SqlData.cpp
+ ${PROJECT_SOURCE_DIR}/tappsd/src/db/DTapps2SqliteDB.cpp
+ ${PROJECT_SOURCE_DIR}/tappsd/src/util/DTapps2Base64.cpp
+ ${PROJECT_SOURCE_DIR}/tappsd/src/util/DTapps2HMAC.cpp
+ ${PROJECT_SOURCE_DIR}/tappsd/src/util/DTapps2Time.cpp
+ ${PROJECT_SOURCE_DIR}/service/drm-tapps.cpp
+ ${PROJECT_SOURCE_DIR}/tadcore/TADCInterface/DUIDGenerator.cpp
+)
+
+INCLUDE_DIRECTORIES(
+ SYSTEM
+ ${DRM_TEST_DEP_INCLUDE_DIRS}
+ ${CMAKE_CURRENT_SOURCE_DIR}/tadcore/include
+ ${CMAKE_CURRENT_SOURCE_DIR}/tappsd/inc
+ ${CMAKE_CURRENT_SOURCE_DIR}/include
+)
+
+ADD_DEFINITIONS("-DDPL_LOGS_ENABLED")
+ADD_DEFINITIONS("-DTEST_CODE_ENABLED")
+
+
+SET_SOURCE_FILES_PROPERTIES(
+ ${DRMTESTUTIL_SRCS}
+ PROPERTIES
+ COMPILE_FLAGS "-fPIE")
+
+ADD_EXECUTABLE(${DRMTESTUTIL} ${DRMTESTUTIL_SRCS})
+
+TARGET_LINK_LIBRARIES(${DRMTESTUTIL}
+ ${DRM_TEST_DEP_LIBRARIES}
+ -ldevice_info
+ -pie
+)
+
+INSTALL(TARGETS ${DRMTESTUTIL}
+ DESTINATION ${TZ_SYS_BIN}
+ PERMISSIONS
+ OWNER_READ
+ OWNER_WRITE
+ OWNER_EXECUTE
+ GROUP_READ
+ GROUP_EXECUTE
+ WORLD_READ
+ WORLD_EXECUTE
+)
+
+INSTALL(FILES
+ ${PROJECT_SOURCE_DIR}/test/sample_contents/DCF/38EIfBurLJ.tpk
+ ${PROJECT_SOURCE_DIR}/test/sample_contents/DCF/8SPXfqc6iL.tpk
+ ${PROJECT_SOURCE_DIR}/test/sample_contents/DCF/FightGuiIF.tpk
+ ${PROJECT_SOURCE_DIR}/test/sample_contents/DCF/basiccoreuiapp_drm.tpk
+ DESTINATION
+ ${TZ_SYS_DATA}/drm_test/DCF/
+)
+
+INSTALL(FILES
+ ${PROJECT_SOURCE_DIR}/test/sample_contents/RO/38EIfBurLJ-1.0.2.ro
+ ${PROJECT_SOURCE_DIR}/test/sample_contents/RO/8SPXfqc6iL-1.0.0.ro
+ ${PROJECT_SOURCE_DIR}/test/sample_contents/RO/FightGuiIF-1.0.0.ro
+ ${PROJECT_SOURCE_DIR}/test/sample_contents/RO/38EIfBurLJ-1.0.2.cert_chain_invalid.ro
+ ${PROJECT_SOURCE_DIR}/test/sample_contents/RO/38EIfBurLJ-1.0.2.cert_invalid.ro
+ ${PROJECT_SOURCE_DIR}/test/sample_contents/RO/38EIfBurLJ-1.0.2.cert_only_selfsigned.ro
+ ${PROJECT_SOURCE_DIR}/test/sample_contents/RO/38EIfBurLJ-1.0.2.signature_invalid.ro
+ ${PROJECT_SOURCE_DIR}/test/sample_contents/RO/8SPXfqc6iL-1.0.0.signature_invalid.ro
+ ${PROJECT_SOURCE_DIR}/test/sample_contents/RO/FightGuiIF-1.0.0.signature_invalid.ro
+ ${PROJECT_SOURCE_DIR}/test/sample_contents/RO/38EIfBurLJ-1.0.2.ro_template
+ DESTINATION
+ ${TZ_SYS_DATA}/drm_test/RO/
+)
+
+INSTALL(FILES
+ ${PROJECT_SOURCE_DIR}/test/sample_contents/DecryptedApp/38EIfBurLJ_dec.tpk
+ ${PROJECT_SOURCE_DIR}/test/sample_contents/DecryptedApp/8SPXfqc6iL_dec.tpk
+ ${PROJECT_SOURCE_DIR}/test/sample_contents/DecryptedApp/FightGuiIF_dec.tpk
+ ${PROJECT_SOURCE_DIR}/test/sample_contents/DecryptedApp/basiccoreuiapp_signed.tpk
+ DESTINATION
+ ${TZ_SYS_DATA}/drm_test/DecryptedApp/
+)
+
+INSTALL(FILES
+ ${PROJECT_SOURCE_DIR}/test/sample_contents/KEYS/ro_test_signer.key
+ DESTINATION
+ ${TZ_SYS_DATA}/drm_test/Key/
+)
+
+INSTALL(FILES
+ ${PROJECT_SOURCE_DIR}/test/sample_contents/KEYS/ro_test_root_ca.pem
+ DESTINATION
+ ${TZ_SYS_SHARE}/tizen_app_drm/root_certs/
+)
+
diff --git a/test/drm_testapps.cpp b/test/drm_testapps.cpp
new file mode 100644
index 0000000..d81f32f
--- /dev/null
+++ b/test/drm_testapps.cpp
@@ -0,0 +1,2987 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 "drm-tizen-apps.h"
+#include "drm-tizen-error.h"
+#include "TADC_Core.h"
+#include "TADC_IF.h"
+#include "DrmFileMgr.h"
+
+#include "DTapps2Rights.h"
+#include "drm_testutil.h"
+#include <tzplatform_config.h>
+
+#if 1
+static int first_key = 0;
+static int second_key = 0;
+static int third_key = 0;
+
+bool _write_logfile(const char *filename, char *buf, unsigned int len)
+{
+ FILE *fd = NULL;
+
+ if ((fd = fopen(filename,"w+b")) == NULL)
+ {
+ return false;
+ }
+
+ fwrite(buf, 1, len,fd);
+ fclose(fd);
+
+ return true;
+}
+
+bool _read_logfile(const char *filename, char *buf, unsigned int *pLen)
+{
+ FILE *fd = NULL;
+ int nReadLen = 0;
+
+ if ((fd = fopen(filename,"r+b")) == NULL)
+ {
+ return false;
+ }
+
+ nReadLen = fread(buf, 1, *pLen,fd);
+ *pLen = nReadLen;
+
+ fclose(fd);
+
+ return true;
+}
+
+bool tc01_VerifyRoSignature_Positive_01(void)
+{
+ char Buf[1024*10] = {0, };
+ const char *pRo = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/RO/38EIfBurLJ-1.0.2.ro");
+
+ FILE *fd = NULL;
+ int nReadLen = 0;
+ long lSize = 0;
+ int nRet = 0;
+
+ printf("tc01_VerifyRoSignature_Positive_01() -------- Started! \n");
+
+ fd = fopen(pRo, "rb");
+ if (fd == NULL)
+ {
+ printf("File is not exist! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ fseek(fd, 0, SEEK_END);
+ lSize = ftell(fd);
+ if (lSize < 0)
+ {
+ printf("fseek() and ftell() failed.");
+ goto CATCH;
+ }
+ rewind(fd);
+
+ memset(Buf, 0x00, sizeof(Buf));
+ nReadLen = fread(Buf, 1, lSize, fd);
+ if (nReadLen >= sizeof(Buf))
+ {
+ printf("Buffer error! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ if (nReadLen != lSize)
+ {
+ printf("File read error! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ nRet = TADC_VerifyROSignature((unsigned char*) Buf);
+ if (nRet != 0)
+ {
+ printf("VerifyROSignature Failed! : %s, %d\n", pRo, nRet);
+ goto CATCH;
+ }
+ if (fd != NULL)
+ {
+ fclose(fd);
+ }
+
+ printf("tc01_VerifyRoSignature_Positive_01() finished! -------- success \n");
+ return true;
+
+CATCH:
+ if (fd != NULL)
+ {
+ fclose(fd);
+ }
+ return false;
+}
+
+bool tc01_VerifyRoSignature_Positive_02(void)
+{
+ char Buf[1024*10] = {0, };
+ const char *pRo = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/RO/8SPXfqc6iL-1.0.0.ro");
+
+ FILE *fd = NULL;
+ int nReadLen = 0;
+ long lSize = 0;
+ int nRet = 0;
+
+ printf("tc01_VerifyRoSignature_Positive_02() -------- Started! \n");
+
+ fd = fopen(pRo, "rb");
+ if (fd == NULL)
+ {
+ printf("File is not exist! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ fseek(fd, 0, SEEK_END);
+ lSize = ftell(fd);
+ if (lSize < 0)
+ {
+ printf("fseek() and ftell() failed.");
+ goto CATCH;
+ }
+ rewind(fd);
+
+ memset(Buf, 0x00, sizeof(Buf));
+ nReadLen = fread(Buf, 1, lSize, fd);
+ if (nReadLen >= sizeof(Buf))
+ {
+ printf("Buffer error! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ if (nReadLen != lSize)
+ {
+ printf("File read error! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ nRet = TADC_VerifyROSignature((unsigned char*) Buf);
+ if (nRet != 0)
+ {
+ printf("VerifyROSignature Failed! : %s, %d\n", pRo, nRet);
+ goto CATCH;
+ }
+ if (fd != NULL)
+ {
+ fclose(fd);
+ }
+
+ printf("tc01_VerifyRoSignature_Positive_02() finished! -------- success \n");
+ return true;
+
+CATCH:
+ if (fd != NULL)
+ {
+ fclose(fd);
+ }
+ return false;
+}
+
+bool tc01_VerifyRoSignature_Positive_03(void)
+{
+ char Buf[1024*10] = {0, };
+ const char *pRo = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/RO/FightGuiIF-1.0.0.ro");
+
+ FILE *fd = NULL;
+ int nReadLen = 0;
+ long lSize = 0;
+ int nRet = 0;
+
+ printf("tc01_VerifyRoSignature_Positive_03() -------- Started! \n");
+
+ fd = fopen(pRo, "rb");
+ if (fd == NULL)
+ {
+ printf("File is not exist! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ fseek(fd, 0, SEEK_END);
+ lSize = ftell(fd);
+ if (lSize < 0)
+ {
+ printf("fseek() and ftell() failed.");
+ goto CATCH;
+ }
+ rewind(fd);
+
+ memset(Buf, 0x00, sizeof(Buf));
+ nReadLen = fread(Buf, 1, lSize, fd);
+ if (nReadLen >= sizeof(Buf))
+ {
+ printf("Buffer error! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ if (nReadLen != lSize)
+ {
+ printf("File read error! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ nRet = TADC_VerifyROSignature((unsigned char*) Buf);
+ if (nRet != 0)
+ {
+ printf("VerifyROSignature Failed! : %s, %d\n", pRo, nRet);
+ goto CATCH;
+ }
+ if (fd != NULL)
+ {
+ fclose(fd);
+ }
+
+ printf("tc01_VerifyRoSignature_Positive_03() finished! -------- success \n");
+ return true;
+
+CATCH:
+ if (fd != NULL)
+ {
+ fclose(fd);
+ }
+ return false;
+}
+
+bool tc02_VerifyRoSignature_Negative_Cert_01(void)
+{
+ char Buf[1024*10] = {0, };
+ const char *pRo = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/RO/38EIfBurLJ-1.0.2.cert_only_selfsigned.ro");
+ FILE *fd = NULL;
+ int nReadLen = 0;
+ long lSize = 0;
+ int nRet = 0;
+
+ printf("tc02_VerifyRoSignature_Negative_Cert_01() -------- Started! \n");
+
+ fd = fopen(pRo, "rb");
+ if (fd == NULL)
+ {
+ printf("File is not exist! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ fseek(fd, 0, SEEK_END);
+ lSize = ftell(fd);
+ if (lSize < 0)
+ {
+ printf("fseek() and ftell() failed.");
+ goto CATCH;
+ }
+ rewind(fd);
+
+ memset(Buf, 0x00, sizeof(Buf));
+ nReadLen = fread(Buf, 1, lSize, fd);
+ if (nReadLen >= sizeof(Buf))
+ {
+ printf("Buffer error! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ if (nReadLen != lSize)
+ {
+ printf("File read error! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ nRet = TADC_VerifyROSignature((unsigned char*) Buf);
+ if (nRet >= 0)
+ {
+ printf("VerifyROSignature have to be failed. But success! : %s, %d\n", pRo, nRet);
+ goto CATCH;
+ }
+ if (fd != NULL)
+ {
+ fclose(fd);
+ }
+
+ printf("tc02_VerifyRoSignature_Negative_Cert_01 finished! -------- success \n");
+ return true;
+
+CATCH:
+ if (fd != NULL)
+ {
+ fclose(fd);
+ }
+ return false;
+}
+
+bool tc02_VerifyRoSignature_Negative_Cert_02(void)
+{
+ char Buf[1024*10] = {0, };
+ const char *pRo = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/RO/38EIfBurLJ-1.0.2.cert_chain_invalid.ro");
+ FILE *fd = NULL;
+ int nReadLen = 0;
+ long lSize = 0;
+ int nRet = 0;
+
+ printf("tc02_VerifyRoSignature_Negative_Cert_02() -------- Started! \n");
+
+ fd = fopen(pRo, "rb");
+ if (fd == NULL)
+ {
+ printf("File is not exist! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ fseek(fd, 0, SEEK_END);
+ lSize = ftell(fd);
+ if (lSize < 0)
+ {
+ printf("fseek() and ftell() failed.");
+ goto CATCH;
+ }
+ rewind(fd);
+
+ memset(Buf, 0x00, sizeof(Buf));
+ nReadLen = fread(Buf, 1, lSize, fd);
+ if (nReadLen >= sizeof(Buf))
+ {
+ printf("Buffer error! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ if (nReadLen != lSize)
+ {
+ printf("File read error! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ nRet = TADC_VerifyROSignature((unsigned char*) Buf);
+ if (nRet >= 0)
+ {
+ printf("VerifyROSignature have to be failed. But success! : %s, %d\n", pRo, nRet);
+ goto CATCH;
+ }
+ if (fd != NULL)
+ {
+ fclose(fd);
+ }
+
+ printf("tc02_VerifyRoSignature_Negative_Cert_02 finished! -------- success \n");
+ return true;
+
+CATCH:
+ if (fd != NULL)
+ {
+ fclose(fd);
+ }
+ return false;
+}
+
+bool tc02_VerifyRoSignature_Negative_Cert_03(void)
+{
+ char Buf[1024*10] = {0, };
+ const char *pRo = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/RO/38EIfBurLJ-1.0.2.cert_invalid.ro");
+ FILE *fd = NULL;
+ int nReadLen = 0;
+ long lSize = 0;
+ int nRet = 0;
+
+ printf("tc02_VerifyRoSignature_Negative_Cert_03() -------- Started! \n");
+
+ fd = fopen(pRo, "rb");
+ if (fd == NULL)
+ {
+ printf("File is not exist! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ fseek(fd, 0, SEEK_END);
+ lSize = ftell(fd);
+ if (lSize < 0)
+ {
+ printf("fseek() and ftell() failed.");
+ goto CATCH;
+ }
+ rewind(fd);
+
+ memset(Buf, 0x00, sizeof(Buf));
+ nReadLen = fread(Buf, 1, lSize, fd);
+ if (nReadLen >= sizeof(Buf))
+ {
+ printf("Buffer error! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ if (nReadLen != lSize)
+ {
+ printf("File read error! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ nRet = TADC_VerifyROSignature((unsigned char*) Buf);
+ if (nRet >= 0)
+ {
+ printf("VerifyROSignature have to be failed. But success! : %s, %d\n", pRo, nRet);
+ goto CATCH;
+ }
+ if (fd != NULL)
+ {
+ fclose(fd);
+ }
+
+ printf("tc02_VerifyRoSignature_Negative_Cert_03 finished! -------- success \n");
+ return true;
+
+CATCH:
+ if (fd != NULL)
+ {
+ fclose(fd);
+ }
+ return false;
+}
+
+bool tc03_VerifyRoSignature_Negative_Signature_01(void)
+{
+ char Buf[1024*10] = {0, };
+ const char *pRo = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/RO/FightGuiIF-1.0.0.signature_invalid.ro");
+ FILE *fd = NULL;
+ int nReadLen = 0;
+ long lSize = 0;
+ int nRet = 0;
+
+ printf("tc03_VerifyRoSignature_Negative_Signature_01() -------- Started! \n");
+
+ fd = fopen(pRo, "rb");
+ if (fd == NULL)
+ {
+ printf("File is not exist! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ fseek(fd, 0, SEEK_END);
+ lSize = ftell(fd);
+ if (lSize < 0)
+ {
+ printf("fseek() and ftell() failed.");
+ goto CATCH;
+ }
+ rewind(fd);
+
+ memset(Buf, 0x00, sizeof(Buf));
+ nReadLen = fread(Buf, 1, lSize, fd);
+ if (nReadLen >= sizeof(Buf))
+ {
+ printf("Buffer error! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ if (nReadLen != lSize)
+ {
+ printf("File read error! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ nRet = TADC_VerifyROSignature((unsigned char*) Buf);
+ if (nRet >= 0)
+ {
+ printf("VerifyROSignature have to be failed. But success! : %s, %d\n", pRo, nRet);
+ goto CATCH;
+ }
+ if (fd != NULL)
+ {
+ fclose(fd);
+ }
+
+ printf("tc03_VerifyRoSignature_Negative_Signature_01() finished! -------- success \n");
+
+ return true;
+
+CATCH:
+ if (fd != NULL)
+ {
+ fclose(fd);
+ }
+ return false;
+}
+
+bool tc03_VerifyRoSignature_Negative_Signature_02(void)
+{
+ char Buf[1024*10] = {0, };
+ const char *pRo = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/RO/38EIfBurLJ-1.0.2.signature_invalid.ro");
+ FILE *fd = NULL;
+ int nReadLen = 0;
+ long lSize = 0;
+ int nRet = 0;
+
+ printf("tc03_VerifyRoSignature_Negative_Signature_02() -------- Started! \n");
+
+ fd = fopen(pRo, "rb");
+ if (fd == NULL)
+ {
+ printf("File is not exist! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ fseek(fd, 0, SEEK_END);
+ lSize = ftell(fd);
+ if (lSize < 0)
+ {
+ printf("fseek() and ftell() failed.");
+ goto CATCH;
+ }
+ rewind(fd);
+
+ memset(Buf, 0x00, sizeof(Buf));
+ nReadLen = fread(Buf, 1, lSize, fd);
+ if (nReadLen >= sizeof(Buf))
+ {
+ printf("Buffer error! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ if (nReadLen != lSize)
+ {
+ printf("File read error! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ nRet = TADC_VerifyROSignature((unsigned char*) Buf);
+ if (nRet >= 0)
+ {
+ printf("VerifyROSignature have to be failed. But success! : %s, %d\n", pRo, nRet);
+ goto CATCH;
+ }
+ if (fd != NULL)
+ {
+ fclose(fd);
+ }
+
+ printf("tc03_VerifyRoSignature_Negative_Signature_01() finished! -------- success \n");
+
+ return true;
+
+CATCH:
+ if (fd != NULL)
+ {
+ fclose(fd);
+ }
+ return false;
+}
+
+bool tc03_VerifyRoSignature_Negative_Signature_03(void)
+{
+ char Buf[1024*10] = {0, };
+ const char *pRo = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/RO/8SPXfqc6iL-1.0.0.signature_invalid.ro");
+ FILE *fd = NULL;
+ int nReadLen = 0;
+ long lSize = 0;
+ int nRet = 0;
+
+ printf("tc03_VerifyRoSignature_Negative_Signature_03() -------- Started! \n");
+
+ fd = fopen(pRo, "rb");
+ if (fd == NULL)
+ {
+ printf("File is not exist! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ fseek(fd, 0, SEEK_END);
+ lSize = ftell(fd);
+ if (lSize < 0)
+ {
+ printf("fseek() and ftell() failed.");
+ goto CATCH;
+ }
+ rewind(fd);
+
+ memset(Buf, 0x00, sizeof(Buf));
+ nReadLen = fread(Buf, 1, lSize, fd);
+ if (nReadLen >= sizeof(Buf))
+ {
+ printf("Buffer error! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ if (nReadLen != lSize)
+ {
+ printf("File read error! : %s\n", pRo);
+ goto CATCH;
+ }
+
+ nRet = TADC_VerifyROSignature((unsigned char*) Buf);
+ if (nRet >= 0)
+ {
+ printf("VerifyROSignature have to be failed. But success! : %s, %d\n", pRo, nRet);
+ goto CATCH;
+ }
+ if (fd != NULL)
+ {
+ fclose(fd);
+ }
+
+ printf("tc03_VerifyRoSignature_Negative_Signature_03() finished! -------- success \n");
+
+ return true;
+
+CATCH:
+ if (fd != NULL)
+ {
+ fclose(fd);
+ }
+ return false;
+}
+
+bool tc04_isDrmFile_Positive_01(void)
+{
+ const char *pDCF = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/DCF/38EIfBurLJ.tpk");
+ int nRet = 0;
+
+ printf("tc04_isDrmFile_Positive_01() -------- Started!\n");
+
+ nRet = drm_tizen_is_drm_file(pDCF, strlen(pDCF));
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("drm_tizen_is_drm_file failed. Path = %s, Ret = %d\n", pDCF, nRet);
+ printf("%s file is not TADC file!\n", pDCF);
+ return false;
+ }
+
+ printf("tc04_isDrmFile_Positive_01() finished! -------- success \n");
+
+ return true;
+}
+
+bool tc04_isDrmFile_Positive_02(void)
+{
+ const char *pDCF = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/DCF/8SPXfqc6iL.tpk");
+ int nRet = 0;
+
+ printf("tc04_isDrmFile_Positive_02() -------- Started!\n");
+
+ nRet = drm_tizen_is_drm_file(pDCF, strlen(pDCF));
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("drm_tizen_is_drm_file failed. Path = %s, Ret = %d\n", pDCF, nRet);
+ printf("%s file is not TADC file!\n", pDCF);
+ return false;
+ }
+
+ printf("tc04_isDrmFile_Positive_02() finished! -------- success \n");
+
+ return true;
+}
+
+bool tc04_isDrmFile_Positive_03(void)
+{
+ const char *pDCF = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/DCF/FightGuiIF.tpk");
+ int nRet = 0;
+
+ printf("tc04_isDrmFile_Positive_03() -------- Started!\n");
+
+ nRet = drm_tizen_is_drm_file(pDCF, strlen(pDCF));
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("drm_tizen_is_drm_file failed. Path = %s, Ret = %d\n", pDCF, nRet);
+ printf("%s file is not TADC file!\n", pDCF);
+ return false;
+ }
+
+ printf("tc04_isDrmFile_Positive_03() finished! -------- success \n");
+
+ return true;
+}
+
+bool tc05_isDrmFile_Negative_01(void)
+{
+ const char *pApp = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/DecryptedApp/38EIfBurLJ_dec.tpk");
+ int nRet = 0;
+
+ printf("tc05_isDrmFile_Negative_01() -------- Started! \n");
+
+ nRet = drm_tizen_is_drm_file(pApp, strlen(pApp));
+ if(nRet == TADC_SUCCESS)
+ {
+ printf("drm_tizen_is_drm_file have to be failed. But Success! Path = %s, Ret = %d\n", pApp, nRet);
+ return false;
+ }
+
+ printf("tc05_isDrmFile_Negative_01 finished! -------- success \n");
+
+ return true;
+}
+
+bool tc05_isDrmFile_Negative_02(void)
+{
+ const char *pApp = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/DecryptedApp/8SPXfqc6iL_dec.tpk");
+ int nRet = 0;
+
+ printf("tc05_isDrmFile_Negative_02() -------- Started! \n");
+
+ nRet = drm_tizen_is_drm_file(pApp, strlen(pApp));
+ if(nRet == TADC_SUCCESS)
+ {
+ printf("drm_tizen_is_drm_file have to be failed. But Success! Path = %s, Ret = %d\n", pApp, nRet);
+ return false;
+ }
+
+ printf("tc05_isDrmFile_Negative_02 finished! -------- success \n");
+
+ return true;
+}
+
+bool tc05_isDrmFile_Negative_03(void)
+{
+ const char *pApp = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/DecryptedApp/FightGuiIF_dec.tpk");
+ int nRet = 0;
+
+ printf("tc05_isDrmFile_Negative_03() -------- Started! \n");
+
+ nRet = drm_tizen_is_drm_file(pApp, strlen(pApp));
+ if(nRet == TADC_SUCCESS)
+ {
+ printf("drm_tizen_is_drm_file have to be failed. But Success! Path = %s, Ret = %d\n", pApp, nRet);
+ return false;
+ }
+
+ printf("tc05_isDrmFile_Negative_03 finished! -------- success \n");
+
+ return true;
+}
+
+bool
+tc06_DrmFileHandlerPositive_01(void)
+{
+ const char *pDCF = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/DCF/38EIfBurLJ.tpk");
+ DrmFileHandler* pDcfHandler = NULL;
+ unsigned char* pBufCEK = NULL;
+ unsigned char pCEK[CEK_SIZE + 1] = {0xB1, 0x03, 0x4F, 0x30, 0xC8, 0x52, 0x45, 0x7E, 0x9D, 0xA2, 0x52, 0x25, 0x2E, 0xA9, 0x9B, 0x2B, 0x25, 0x36, 0xF1, 0x8D, 0x04, 0xD1, 0x4C, 0xE3, 0x96, 0x81, 0xD9, 0x98, 0xBB, 0xD7, 0x7E, 0xCA, 0x00};
+ unsigned char pCID[32] = "38EIfBurLJ-1.0.2";
+
+ long encryptionLevel = 17;
+ long long encryptionRange = 10;
+ long long plainTextSize = 1630724;
+ long long originalEndOffset = 1631570;
+ int nRet = 0;
+
+ printf("tc06_DrmFileHandlerPositive_01() -------- Started! \n");
+
+ pBufCEK = (unsigned char*)malloc(CEK_SIZE + 1);
+ memset(pBufCEK, 0x00, CEK_SIZE + 1);
+
+ pDcfHandler = new DrmFileHandler();
+ if (pDcfHandler == NULL)
+ {
+ goto CATCH;
+ }
+
+ nRet = pDcfHandler->Construct(pDCF);
+ if (nRet != 1)
+ {
+ printf("tc06_DrmFileHandlerPositive_01 - Construct() failed : %s, %x\n", pDCF, nRet);
+ goto CATCH;
+ }
+
+ if (memcmp(pCEK, pDcfHandler->m_pCEK, CEK_SIZE) != 0)
+ {
+ printf("tc06_DrmFileHandlerPositive_01 - CEK Comparison failed : %s\n", pDCF);
+ goto CATCH;
+ }
+
+ if (memcmp(pDCF, pDcfHandler->m_pFilePath, strlen((char*)pDcfHandler->m_pFilePath)) != 0)
+ {
+ printf("tc06_DrmFileHandlerPositive_01 - FilePath Comparison failed : %s\n", pDcfHandler->m_pFilePath);
+ goto CATCH;
+ }
+
+ if (memcmp(pCID, pDcfHandler->m_pCID, strlen((char*)pDcfHandler->m_pCID)) != 0)
+ {
+ printf("tc06_DrmFileHandlerPositive_01 - CID Comparison failed : %s\n", pDcfHandler->m_pCID);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_encryptionLevel != encryptionLevel)
+ {
+ printf("tc06_DrmFileHandlerPositive_01 - encryptionLevel Comparison failed : origin = %ld, result = %ld\n", encryptionLevel, pDcfHandler->m_encryptionLevel);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_encryptionRange != encryptionRange)
+ {
+ printf("tc06_DrmFileHandlerPositive_01 - encryptionRange Comparison failed : origin = %lld, result = %lld\n", encryptionRange, pDcfHandler->m_encryptionRange);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_plaintextSize != plainTextSize)
+ {
+ printf("tc06_DrmFileHandlerPositive_01 - plainTextSize Comparison failed : origin = %lld, result = %lld\n", plainTextSize, pDcfHandler->m_plaintextSize);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_OriginEndOffset != originalEndOffset)
+ {
+ printf("tc06_DrmFileHandlerPositive_01 - originalEndOffset Comparison failed : origin = %lld, result = %lld\n", originalEndOffset, pDcfHandler->m_OriginEndOffset);
+ goto CATCH;
+ }
+
+ if (pDcfHandler != NULL)
+ {
+ delete pDcfHandler;
+ }
+
+ if (pBufCEK != NULL)
+ {
+ free(pBufCEK);
+ }
+
+ printf("tc06_DrmFileHandlerPositive_01 finished! -------- success \n");
+
+ return true;
+
+CATCH:
+ if (pDcfHandler != NULL)
+ {
+ delete pDcfHandler;
+ }
+
+ if (pBufCEK != NULL)
+ {
+ free(pBufCEK);
+ }
+
+ return false;
+}
+
+bool
+tc06_DrmFileHandlerPositive_02(void)
+{
+ const char *pDCF = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/DCF/8SPXfqc6iL.tpk");
+ unsigned char* pBufCEK = NULL;
+ DrmFileHandler* pDcfHandler = NULL;
+ unsigned char pCEK[CEK_SIZE + 1] = {0xBB, 0x87, 0x5D, 0xA8, 0x2C, 0xC4, 0x47, 0x81, 0x90, 0xBA, 0xD9, 0xB0, 0x0C, 0xD2, 0x94, 0xE9, 0x19, 0x0F, 0x24, 0x62, 0x5B, 0x0B, 0x49, 0x7A, 0xAE, 0x8E, 0x1D, 0x88, 0x7F, 0xF9, 0x96, 0xDB, 0x00};
+ unsigned char pCID[32] = "8SPXfqc6iL-1.0.0";
+
+ long encryptionLevel = 17;
+ long long encryptionRange = 10;
+ long long plainTextSize = 705072;
+ long long originalEndOffset = 705914;
+ int nRet = 0;
+
+ printf("tc06_DrmFileHandlerPositive_02() -------- Started! \n");
+
+ pBufCEK = (unsigned char*)malloc(CEK_SIZE + 1);
+ memset(pBufCEK, 0x00, CEK_SIZE + 1);
+
+ pDcfHandler = new DrmFileHandler();
+ if (pDcfHandler == NULL)
+ {
+ goto CATCH;
+ }
+
+ nRet = pDcfHandler->Construct(pDCF);
+ if (nRet != 1)
+ {
+ printf("tc06_DrmFileHandlerPositive_02 - Construct() failed : %s, %x\n", pDCF, nRet);
+ goto CATCH;
+ }
+
+ if (memcmp(pCEK, pDcfHandler->m_pCEK, CEK_SIZE) != 0)
+ {
+ printf("tc06_DrmFileHandlerPositive_02 - CEK Comparison failed : %s\n", pDCF);
+ goto CATCH;
+ }
+
+ if (memcmp(pDCF, pDcfHandler->m_pFilePath, strlen((char*)pDcfHandler->m_pFilePath)) != 0)
+ {
+ printf("tc06_DrmFileHandlerPositive_02 - FilePath Comparison failed : %s\n", pDcfHandler->m_pFilePath);
+ goto CATCH;
+ }
+
+ if (memcmp(pCID, pDcfHandler->m_pCID, strlen((char*)pDcfHandler->m_pCID)) != 0)
+ {
+ printf("tc06_DrmFileHandlerPositive_02 - CID Comparison failed : %s\n", pDcfHandler->m_pCID);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_encryptionLevel != encryptionLevel)
+ {
+ printf("tc06_DrmFileHandlerPositive_02 - encryptionLevel Comparison failed : origin = %ld, result = %ld\n", encryptionLevel, pDcfHandler->m_encryptionLevel);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_encryptionRange != encryptionRange)
+ {
+ printf("tc06_DrmFileHandlerPositive_02 - encryptionRange Comparison failed : origin = %lld, result = %lld\n", encryptionRange, pDcfHandler->m_encryptionRange);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_plaintextSize != plainTextSize)
+ {
+ printf("tc06_DrmFileHandlerPositive_02 - plainTextSize Comparison failed : origin = %lld, result = %lld\n", plainTextSize, pDcfHandler->m_plaintextSize);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_OriginEndOffset != originalEndOffset)
+ {
+ printf("tc06_DrmFileHandlerPositive_02 - originalEndOffset Comparison failed : origin = %lld, result = %lld\n", originalEndOffset, pDcfHandler->m_OriginEndOffset);
+ goto CATCH;
+ }
+
+ if (pDcfHandler != NULL)
+ {
+ delete pDcfHandler;
+ }
+
+ if (pBufCEK != NULL)
+ {
+ free(pBufCEK);
+ }
+
+ printf("tc06_DrmFileHandlerPositive_02 finished! -------- success \n");
+
+ return true;
+
+CATCH:
+ if (pDcfHandler != NULL)
+ {
+ delete pDcfHandler;
+ }
+
+ if (pBufCEK != NULL)
+ {
+ free(pBufCEK);
+ }
+
+ return false;
+}
+
+bool
+tc06_DrmFileHandlerPositive_03(void)
+{
+ const char *pDCF = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/DCF/FightGuiIF.tpk");
+ unsigned char* pBufCEK = NULL;
+ DrmFileHandler* pDcfHandler = NULL;
+ unsigned char pCEK[CEK_SIZE + 1] = {0x34, 0x5A, 0x94, 0x28, 0xC3, 0xF4, 0x44, 0x3F, 0x86, 0x6D, 0xCF, 0xC5, 0x78, 0x1F, 0x23, 0xCE, 0xE9, 0x9B, 0xC4, 0x45, 0xA3, 0x30, 0x47, 0x1E, 0xB4, 0xE0, 0xAF, 0x96, 0x0F, 0xDE, 0xA9, 0xB4, 0x00};
+ unsigned char pCID[32] = "FightGuiIF-1.0.0";
+
+ long encryptionLevel = 17;
+ long long encryptionRange = 10;
+ long long plainTextSize = 45193789;
+ long long originalEndOffset = 45194636;
+ int nRet = 0;
+
+ printf("tc06_DrmFileHandlerPositive_03() -------- Started! \n");
+
+ pBufCEK = (unsigned char*)malloc(CEK_SIZE + 1);
+ memset(pBufCEK, 0x00, CEK_SIZE + 1);
+
+ pDcfHandler = new DrmFileHandler();
+ if (pDcfHandler == NULL)
+ {
+ goto CATCH;
+ }
+
+ nRet = pDcfHandler->Construct(pDCF);
+ if (nRet != 1)
+ {
+ printf("tc06_DrmFileHandlerPositive_03 - Construct() failed : %s, %x\n", pDCF, nRet);
+ goto CATCH;
+ }
+
+ if (memcmp(pCEK, pDcfHandler->m_pCEK, CEK_SIZE) != 0)
+ {
+ printf("tc06_DrmFileHandlerPositive_03 - CEK Comparison failed : %s\n", pDCF);
+ goto CATCH;
+ }
+
+ if (memcmp(pDCF, pDcfHandler->m_pFilePath, strlen((char*)pDcfHandler->m_pFilePath)) != 0)
+ {
+ printf("tc06_DrmFileHandlerPositive_03 - FilePath Comparison failed : %s\n", pDcfHandler->m_pFilePath);
+ goto CATCH;
+ }
+
+ if (memcmp(pCID, pDcfHandler->m_pCID, strlen((char*)pDcfHandler->m_pCID)) != 0)
+ {
+ printf("tc06_DrmFileHandlerPositive_03 - CID Comparison failed : %s\n", pDcfHandler->m_pCID);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_encryptionLevel != encryptionLevel)
+ {
+ printf("tc06_DrmFileHandlerPositive_03 - encryptionLevel Comparison failed : origin = %ld, result = %ld\n", encryptionLevel, pDcfHandler->m_encryptionLevel);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_encryptionRange != encryptionRange)
+ {
+ printf("tc06_DrmFileHandlerPositive_03 - encryptionRange Comparison failed : origin = %lld, result = %lld\n", encryptionRange, pDcfHandler->m_encryptionRange);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_plaintextSize != plainTextSize)
+ {
+ printf("tc06_DrmFileHandlerPositive_03 - plainTextSize Comparison failed : origin = %lld, result = %lld\n", plainTextSize, pDcfHandler->m_plaintextSize);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_OriginEndOffset != originalEndOffset)
+ {
+ printf("tc06_DrmFileHandlerPositive_03 - originalEndOffset Comparison failed : origin = %lld, result = %lld\n", originalEndOffset, pDcfHandler->m_OriginEndOffset);
+ goto CATCH;
+ }
+
+ if (pDcfHandler != NULL)
+ {
+ delete pDcfHandler;
+ }
+
+ if (pBufCEK != NULL)
+ {
+ free(pBufCEK);
+ }
+
+ printf("tc06_DrmFileHandlerPositive_03 finished! -------- success \n");
+
+ return true;
+
+CATCH:
+ if (pDcfHandler != NULL)
+ {
+ delete pDcfHandler;
+ }
+
+ if (pBufCEK != NULL)
+ {
+ free(pBufCEK);
+ }
+
+ return false;
+}
+
+bool tc07_DrmFileMgrPositive_01(void)
+{
+ const char *pDCF = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/DCF/38EIfBurLJ.tpk");
+ int nRet = TADC_SUCCESS;
+
+ DrmFileMgr* pDrmFileMgr = NULL;
+ DrmFileHandler *pDcfHandler = NULL;
+
+ unsigned char pCEK[CEK_SIZE + 1] = {0xB1, 0x03, 0x4F, 0x30, 0xC8, 0x52, 0x45, 0x7E, 0x9D, 0xA2, 0x52, 0x25, 0x2E, 0xA9, 0x9B, 0x2B, 0x25, 0x36, 0xF1, 0x8D, 0x04, 0xD1, 0x4C, 0xE3, 0x96, 0x81, 0xD9, 0x98, 0xBB, 0xD7, 0x7E, 0xCA, 0x00};
+
+ unsigned char pCID[32] = "38EIfBurLJ-1.0.2";
+ long encryptionLevel = 17;
+ long long encryptionRange = 10;
+ long long plainTextSize = 1630724;
+ long long originalEndOffset = 1631570;
+
+ printf("tc07_DrmFileMgrPositive_01() -------- Started! \n");
+
+ pDrmFileMgr = DrmFileMgr::GetInstance();
+
+ nRet = pDrmFileMgr->OpenFileHandler(pDCF, 1, &first_key);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc07_DrmFileMgrPositive_01 - OpenFileHandler() failed : key = %d, file = %s, %x\n", first_key, pDCF, nRet);
+ goto CATCH;
+ }
+
+ nRet = pDrmFileMgr->GetFileHandler(first_key, &pDcfHandler);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc07_DrmFileMgrPositive_01 - GetFileHandler() failed : key = %d, file = %s, %x\n", first_key, pDCF, nRet);
+ goto CATCH;
+ }
+
+ if (memcmp(pCEK, pDcfHandler->m_pCEK, CEK_SIZE) != 0)
+ {
+ printf("tc07_DrmFileMgrPositive_01 - CEK Comparison failed : %s\n", pDCF);
+ goto CATCH;
+ }
+
+ if (memcmp(pDCF, pDcfHandler->m_pFilePath, strlen((char*)pDcfHandler->m_pFilePath)) != 0)
+ {
+ printf("tc07_DrmFileMgrPositive_01 - FilePath Comparison failed : %s\n", pDcfHandler->m_pFilePath);
+ goto CATCH;
+ }
+
+ if (memcmp(pCID, pDcfHandler->m_pCID, strlen((char*)pDcfHandler->m_pCID)) != 0)
+ {
+ printf("tc07_DrmFileMgrPositive_01 - CID Comparison failed : %s\n", pDcfHandler->m_pCID);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_encryptionLevel != encryptionLevel)
+ {
+ printf("tc07_DrmFileMgrPositive_01 - encryptionLevel Comparison failed : origin = %ld, result = %ld\n", encryptionLevel, pDcfHandler->m_encryptionLevel);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_encryptionRange != encryptionRange)
+ {
+ printf("tc07_DrmFileMgrPositive_01 - encryptionRange Comparison failed : origin = %lld, result = %lld\n", encryptionRange, pDcfHandler->m_encryptionRange);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_plaintextSize != plainTextSize)
+ {
+ printf("tc07_DrmFileMgrPositive_01 - plainTextSize Comparison failed : origin = %lld, result = %lld\n", plainTextSize, pDcfHandler->m_plaintextSize);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_OriginEndOffset != originalEndOffset)
+ {
+ printf("tc07_DrmFileMgrPositive_01 - originalEndOffset Comparison failed : origin = %lld, result = %lld\n", originalEndOffset, pDcfHandler->m_OriginEndOffset);
+ goto CATCH;
+ }
+
+ printf("tc07_DrmFileMgrPositive_01 finished! -------- success \n");
+
+ return true;
+
+CATCH:
+
+ return false;
+}
+
+bool tc07_DrmFileMgrPositive_02(void)
+{
+ const char *pDCF = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/DCF/8SPXfqc6iL.tpk");
+ int nRet = TADC_SUCCESS;
+
+ DrmFileMgr* pDrmFileMgr = NULL;
+ DrmFileHandler *pDcfHandler = NULL;
+
+ unsigned char pCEK[CEK_SIZE + 1] = {0xBB, 0x87, 0x5D, 0xA8, 0x2C, 0xC4, 0x47, 0x81, 0x90, 0xBA, 0xD9, 0xB0, 0x0C, 0xD2, 0x94, 0xE9, 0x19, 0x0F, 0x24, 0x62, 0x5B, 0x0B, 0x49, 0x7A, 0xAE, 0x8E, 0x1D, 0x88, 0x7F, 0xF9, 0x96, 0xDB, 0x00};
+ unsigned char pCID[32] = "8SPXfqc6iL-1.0.0";
+
+ long encryptionLevel = 17;
+ long long encryptionRange = 10;
+ long long plainTextSize = 705072;
+ long long originalEndOffset = 705914;
+
+ printf("tc07_DrmFileMgrPositive_02() -------- Started! \n");
+
+ pDrmFileMgr = DrmFileMgr::GetInstance();
+
+ nRet = pDrmFileMgr->OpenFileHandler(pDCF, 1, &second_key);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc07_DrmFileMgrPositive_02 - OpenFileHandler() failed : key = %d, file = %s, %x\n", second_key, pDCF, nRet);
+ goto CATCH;
+ }
+
+ nRet = pDrmFileMgr->GetFileHandler(second_key, &pDcfHandler);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc07_DrmFileMgrPositive_02 - GetFileHandler() failed : key = %d, file = %s, %x\n", second_key, pDCF, nRet);
+ goto CATCH;
+ }
+
+ if (memcmp(pCEK, pDcfHandler->m_pCEK, CEK_SIZE) != 0)
+ {
+ printf("tc07_DrmFileMgrPositive_02 - CEK Comparison failed : %s\n", pDCF);
+ goto CATCH;
+ }
+
+ if (memcmp(pDCF, pDcfHandler->m_pFilePath, strlen((char*)pDcfHandler->m_pFilePath)) != 0)
+ {
+ printf("tc07_DrmFileMgrPositive_02 - FilePath Comparison failed : %s\n", pDcfHandler->m_pFilePath);
+ goto CATCH;
+ }
+
+ if (memcmp(pCID, pDcfHandler->m_pCID, strlen((char*)pDcfHandler->m_pCID)) != 0)
+ {
+ printf("tc07_DrmFileMgrPositive_02 - CID Comparison failed : %s\n", pDcfHandler->m_pCID);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_encryptionLevel != encryptionLevel)
+ {
+ printf("tc07_DrmFileMgrPositive_02 - encryptionLevel Comparison failed : origin = %ld, result = %ld\n", encryptionLevel, pDcfHandler->m_encryptionLevel);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_encryptionRange != encryptionRange)
+ {
+ printf("tc07_DrmFileMgrPositive_02 - encryptionRange Comparison failed : origin = %lld, result = %lld\n", encryptionRange, pDcfHandler->m_encryptionRange);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_plaintextSize != plainTextSize)
+ {
+ printf("tc07_DrmFileMgrPositive_02 - plainTextSize Comparison failed : origin = %lld, result = %lld\n", plainTextSize, pDcfHandler->m_plaintextSize);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_OriginEndOffset != originalEndOffset)
+ {
+ printf("tc07_DrmFileMgrPositive_02 - originalEndOffset Comparison failed : origin = %lld, result = %lld\n", originalEndOffset, pDcfHandler->m_OriginEndOffset);
+ goto CATCH;
+ }
+
+ printf("tc07_DrmFileMgrPositive_02 finished! -------- success \n");
+
+ return true;
+
+CATCH:
+
+ return false;
+}
+
+bool tc07_DrmFileMgrPositive_03(void)
+{
+ const char *pDCF = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/DCF/FightGuiIF.tpk");
+ int nRet = TADC_SUCCESS;
+
+ DrmFileMgr* pDrmFileMgr = NULL;
+ DrmFileHandler *pDcfHandler = NULL;
+
+ unsigned char pCEK[CEK_SIZE + 1] = {0x34, 0x5A, 0x94, 0x28, 0xC3, 0xF4, 0x44, 0x3F, 0x86, 0x6D, 0xCF, 0xC5, 0x78, 0x1F, 0x23, 0xCE, 0xE9, 0x9B, 0xC4, 0x45, 0xA3, 0x30, 0x47, 0x1E, 0xB4, 0xE0, 0xAF, 0x96, 0x0F, 0xDE, 0xA9, 0xB4, 0x00};
+
+ unsigned char pCID[32] = "FightGuiIF-1.0.0";
+
+ long encryptionLevel = 17;
+ long long encryptionRange = 10;
+ long long plainTextSize = 45193789;
+ long long originalEndOffset = 45194636;
+
+ printf("tc07_DrmFileMgrPositive_03() -------- Started! \n");
+
+ pDrmFileMgr = DrmFileMgr::GetInstance();
+
+ nRet = pDrmFileMgr->OpenFileHandler(pDCF, 1, &third_key);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc07_DrmFileMgrPositive_03 - OpenFileHandler() failed : key = %d, file = %s, %x\n", third_key, pDCF, nRet);
+ goto CATCH;
+ }
+
+ nRet = pDrmFileMgr->GetFileHandler(third_key, &pDcfHandler);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc07_DrmFileMgrPositive_03 - GetFileHandler() failed : key = %d, file = %s, %x\n", third_key, pDCF, nRet);
+ goto CATCH;
+ }
+
+ if (memcmp(pCEK, pDcfHandler->m_pCEK, CEK_SIZE) != 0)
+ {
+ printf("tc07_DrmFileMgrPositive_03 - CEK Comparison failed : %s\n", pDCF);
+ goto CATCH;
+ }
+
+ if (memcmp(pDCF, pDcfHandler->m_pFilePath, strlen((char*)pDcfHandler->m_pFilePath)) != 0)
+ {
+ printf("tc07_DrmFileMgrPositive_03 - FilePath Comparison failed : %s\n", pDcfHandler->m_pFilePath);
+ goto CATCH;
+ }
+
+ if (memcmp(pCID, pDcfHandler->m_pCID, strlen((char*)pDcfHandler->m_pCID)) != 0)
+ {
+ printf("tc07_DrmFileMgrPositive_03 - CID Comparison failed : %s\n", pDcfHandler->m_pCID);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_encryptionLevel != encryptionLevel)
+ {
+ printf("tc07_DrmFileMgrPositive_03 - encryptionLevel Comparison failed : origin = %ld, result = %ld\n", encryptionLevel, pDcfHandler->m_encryptionLevel);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_encryptionRange != encryptionRange)
+ {
+ printf("tc07_DrmFileMgrPositive_03 - encryptionRange Comparison failed : origin = %lld, result = %lld\n", encryptionRange, pDcfHandler->m_encryptionRange);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_plaintextSize != plainTextSize)
+ {
+ printf("tc07_DrmFileMgrPositive_03 - plainTextSize Comparison failed : origin = %lld, result = %lld\n", plainTextSize, pDcfHandler->m_plaintextSize);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_OriginEndOffset != originalEndOffset)
+ {
+ printf("tc07_DrmFileMgrPositive_03 - originalEndOffset Comparison failed : origin = %lld, result = %lld\n", originalEndOffset, pDcfHandler->m_OriginEndOffset);
+ goto CATCH;
+ }
+
+ printf("tc07_DrmFileMgrPositive_03 finished! -------- success \n");
+
+ return true;
+
+CATCH:
+
+ return false;
+}
+
+bool tc08_DrmFileMgrPositive_GetFileHandler_01(void)
+{
+ const char *pDCF = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/DCF/38EIfBurLJ.tpk");
+ int nRet = TADC_SUCCESS;
+
+ DrmFileMgr* pDrmFileMgr = NULL;
+ DrmFileHandler *pDcfHandler = NULL;
+
+ unsigned char pCEK[CEK_SIZE + 1] = {0xB1, 0x03, 0x4F, 0x30, 0xC8, 0x52, 0x45, 0x7E, 0x9D, 0xA2, 0x52, 0x25, 0x2E, 0xA9, 0x9B, 0x2B, 0x25, 0x36, 0xF1, 0x8D, 0x04, 0xD1, 0x4C, 0xE3, 0x96, 0x81, 0xD9, 0x98, 0xBB, 0xD7, 0x7E, 0xCA, 0x00};
+
+ unsigned char pCID[32] = "38EIfBurLJ-1.0.2";
+
+ long encryptionLevel = 17;
+ long long encryptionRange = 10;
+ long long plainTextSize = 1630724;
+ long long originalEndOffset = 1631570;
+
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_01() -------- Started! \n");
+
+ pDrmFileMgr = DrmFileMgr::GetInstance();
+
+ nRet = pDrmFileMgr->GetFileHandler(first_key, &pDcfHandler);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_01 failed : key = %d, file = %s, %x\n", first_key, pDCF, nRet);
+ goto CATCH;
+ }
+
+ if (memcmp(pCEK, pDcfHandler->m_pCEK, CEK_SIZE) != 0)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_01 - CEK Comparison failed : %s\n", pDCF);
+ goto CATCH;
+ }
+
+ if (memcmp(pDCF, pDcfHandler->m_pFilePath, strlen((char*)pDcfHandler->m_pFilePath)) != 0)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_01 - FilePath Comparison failed : %s\n", pDcfHandler->m_pFilePath);
+ goto CATCH;
+ }
+
+ if (memcmp(pCID, pDcfHandler->m_pCID, strlen((char*)pDcfHandler->m_pCID)) != 0)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_01 - CID Comparison failed : %s\n", pDcfHandler->m_pCID);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_encryptionLevel != encryptionLevel)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_01 - encryptionLevel Comparison failed : origin = %ld, result = %ld\n", encryptionLevel, pDcfHandler->m_encryptionLevel);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_encryptionRange != encryptionRange)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_01 - encryptionRange Comparison failed : origin = %lld, result = %lld\n", encryptionRange, pDcfHandler->m_encryptionRange);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_plaintextSize != plainTextSize)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_01 - plainTextSize Comparison failed : origin = %lld, result = %lld\n", plainTextSize, pDcfHandler->m_plaintextSize);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_OriginEndOffset != originalEndOffset)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_01 - originalEndOffset Comparison failed : origin = %lld, result = %lld\n", originalEndOffset, pDcfHandler->m_OriginEndOffset);
+ goto CATCH;
+ }
+
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_01 finished! -------- success \n");
+
+ return true;
+
+CATCH:
+
+ return false;
+}
+
+bool tc08_DrmFileMgrPositive_GetFileHandler_02(void)
+{
+ const char *pDCF = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/DCF/8SPXfqc6iL.tpk");
+ int nRet = TADC_SUCCESS;
+
+ DrmFileMgr* pDrmFileMgr = NULL;
+ DrmFileHandler *pDcfHandler = NULL;
+
+ unsigned char pCEK[CEK_SIZE + 1] = {0xBB, 0x87, 0x5D, 0xA8, 0x2C, 0xC4, 0x47, 0x81, 0x90, 0xBA, 0xD9, 0xB0, 0x0C, 0xD2, 0x94, 0xE9, 0x19, 0x0F, 0x24, 0x62, 0x5B, 0x0B, 0x49, 0x7A, 0xAE, 0x8E, 0x1D, 0x88, 0x7F, 0xF9, 0x96, 0xDB, 0x00};
+
+ unsigned char pCID[32] = "8SPXfqc6iL-1.0.0";
+
+ long encryptionLevel = 17;
+ long long encryptionRange = 10;
+ long long plainTextSize = 705072;
+ long long originalEndOffset = 705914;
+
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_02() -------- Started! \n");
+
+ pDrmFileMgr = DrmFileMgr::GetInstance();
+
+ nRet = pDrmFileMgr->GetFileHandler(second_key, &pDcfHandler);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_02 failed : key = %d, file = %s, %x\n", second_key, pDCF, nRet);
+ goto CATCH;
+ }
+
+ if (memcmp(pCEK, pDcfHandler->m_pCEK, CEK_SIZE) != 0)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_02 - CEK Comparison failed : %s\n", pDCF);
+ goto CATCH;
+ }
+
+ if (memcmp(pDCF, pDcfHandler->m_pFilePath, strlen((char*)pDcfHandler->m_pFilePath)) != 0)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_02 - FilePath Comparison failed : %s\n", pDcfHandler->m_pFilePath);
+ goto CATCH;
+ }
+
+ if (memcmp(pCID, pDcfHandler->m_pCID, strlen((char*)pDcfHandler->m_pCID)) != 0)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_02 - CID Comparison failed : %s\n", pDcfHandler->m_pCID);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_encryptionLevel != encryptionLevel)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_02 - encryptionLevel Comparison failed : origin = %ld, result = %ld\n", encryptionLevel, pDcfHandler->m_encryptionLevel);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_encryptionRange != encryptionRange)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_02 - encryptionRange Comparison failed : origin = %lld, result = %lld\n", encryptionRange, pDcfHandler->m_encryptionRange);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_plaintextSize != plainTextSize)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_02 - plainTextSize Comparison failed : origin = %lld, result = %lld\n", plainTextSize, pDcfHandler->m_plaintextSize);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_OriginEndOffset != originalEndOffset)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_02 - originalEndOffset Comparison failed : origin = %lld, result = %lld\n", originalEndOffset, pDcfHandler->m_OriginEndOffset);
+ goto CATCH;
+ }
+
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_02 finished! -------- success \n");
+
+ return true;
+
+CATCH:
+
+ return false;
+}
+
+bool tc08_DrmFileMgrPositive_GetFileHandler_03(void)
+{
+ const char *pDCF = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/DCF/FightGuiIF.tpk");
+ int nRet = TADC_SUCCESS;
+
+ DrmFileMgr* pDrmFileMgr = NULL;
+ DrmFileHandler *pDcfHandler = NULL;
+
+ unsigned char pCEK[CEK_SIZE + 1] = {0x34, 0x5A, 0x94, 0x28, 0xC3, 0xF4, 0x44, 0x3F, 0x86, 0x6D, 0xCF, 0xC5, 0x78, 0x1F, 0x23, 0xCE, 0xE9, 0x9B, 0xC4, 0x45, 0xA3, 0x30, 0x47, 0x1E, 0xB4, 0xE0, 0xAF, 0x96, 0x0F, 0xDE, 0xA9, 0xB4, 0x00};
+
+ unsigned char pCID[32] = "FightGuiIF-1.0.0";
+
+ long encryptionLevel = 17;
+ long long encryptionRange = 10;
+ long long plainTextSize = 45193789;
+ long long originalEndOffset = 45194636;
+
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_03() -------- Started! \n");
+
+ pDrmFileMgr = DrmFileMgr::GetInstance();
+
+ nRet = pDrmFileMgr->GetFileHandler(third_key, &pDcfHandler);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_03 failed : key = %d, file = %s, %x\n", third_key, pDCF, nRet);
+ goto CATCH;
+ }
+
+ if (memcmp(pCEK, pDcfHandler->m_pCEK, CEK_SIZE) != 0)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_03 - CEK Comparison failed : %s\n", pDCF);
+ goto CATCH;
+ }
+
+ if (memcmp(pDCF, pDcfHandler->m_pFilePath, strlen((char*)pDcfHandler->m_pFilePath)) != 0)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_03 - FilePath Comparison failed : %s\n", pDcfHandler->m_pFilePath);
+ goto CATCH;
+ }
+
+ if (memcmp(pCID, pDcfHandler->m_pCID, strlen((char*)pDcfHandler->m_pCID)) != 0)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_03 - CID Comparison failed : %s\n", pDcfHandler->m_pCID);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_encryptionLevel != encryptionLevel)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_03 - encryptionLevel Comparison failed : origin = %ld, result = %ld\n", encryptionLevel, pDcfHandler->m_encryptionLevel);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_encryptionRange != encryptionRange)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_03 - encryptionRange Comparison failed : origin = %lld, result = %lld\n", encryptionRange, pDcfHandler->m_encryptionRange);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_plaintextSize != plainTextSize)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_03 - plainTextSize Comparison failed : origin = %lld, result = %lld\n", plainTextSize, pDcfHandler->m_plaintextSize);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_OriginEndOffset != originalEndOffset)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_03 - originalEndOffset Comparison failed : origin = %lld, result = %lld\n", originalEndOffset, pDcfHandler->m_OriginEndOffset);
+ goto CATCH;
+ }
+
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_03 finished! -------- success \n");
+
+ return true;
+
+CATCH:
+
+ return false;
+}
+
+bool tc09_DrmFileMgrPositive_FileAPI_01(void)
+{
+ const char *pDCF = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/DCF/38EIfBurLJ.tpk");
+ int nRet = TADC_SUCCESS;
+
+ DrmFileMgr* pDrmFileMgr = NULL;
+ DrmFileHandler *pDcfHandler = NULL;
+
+ long long originalEndOffset = 1631570;
+ long long DrmCurOffset = 0;
+ long long OriginCurOffset = 846;
+ long long i = 0;
+
+ printf("tc09_DrmFileMgrPositive_FileAPI_01() -------- Started! \n");
+
+ pDrmFileMgr = DrmFileMgr::GetInstance();
+
+ nRet = pDrmFileMgr->GetFileHandler(first_key, &pDcfHandler);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_01 failed : key = %d, file = %s, %x\n", first_key, pDCF, nRet);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_OriginEndOffset != originalEndOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_01 - originalEndOffset Comparison failed : origin = %lld, result = %lld\n", originalEndOffset, pDcfHandler->m_OriginEndOffset);
+ goto CATCH;
+ }
+
+ if (OriginCurOffset != pDcfHandler->m_OriginCurOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_01 - originalCurOffset Comparison failed : origin = %lld, result = %lld\n", OriginCurOffset, pDcfHandler->m_OriginCurOffset);
+ goto CATCH;
+ }
+
+ for (i = 0 ; i <= pDcfHandler->m_DrmEndOffset ; i++)
+ {
+ nRet = pDcfHandler->DrmSeek(i, SEEK_SET);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 DrmSeek failed (SEEK_SET, forward) : key = %d, file = %s, i = %lld, ret = %x\n", first_key, pDCF, i, nRet);
+ goto CATCH;
+ }
+
+ DrmCurOffset = pDcfHandler->DrmTell();
+ if (DrmCurOffset != pDcfHandler->m_DrmCurOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_01 - DrmCurOffset Comparison failed (SEEK_SET, forward) : origin = %lld, result = %lld, i = %lld\n", DrmCurOffset, pDcfHandler->m_DrmCurOffset, i);
+ goto CATCH;
+ }
+ }
+ if (DrmCurOffset != pDcfHandler->m_DrmEndOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_01 DrmSeek failed (SEEK_SET, forward), DrmCurOffset = %lld, RealEndOffset = %lld, %x\n", DrmCurOffset, pDcfHandler->m_DrmEndOffset, nRet);
+ goto CATCH;
+ }
+
+ for (i = pDcfHandler->m_DrmEndOffset ; i >= 0 ; i--)
+ {
+ nRet = pDcfHandler->DrmSeek(i, SEEK_SET);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_01 DrmSeek failed (SEEK_SET, backward) : key=%d, file=%s, i=%lld, %x\n", first_key, pDCF, i, nRet);
+ goto CATCH;
+ }
+
+ DrmCurOffset = pDcfHandler->DrmTell();
+ if (DrmCurOffset != pDcfHandler->m_DrmCurOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_01 - DrmCurOffset Comparison failed (SEEK_SET, backward) : origin = %lld, result = %lld, i=%lld\n", DrmCurOffset, pDcfHandler->m_DrmCurOffset, i);
+ goto CATCH;
+ }
+ }
+ if (DrmCurOffset != 0)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_01 DrmSeek failed (SEEK_SET, backward), DrmCurOffset = %lld, %x\n", DrmCurOffset, nRet);
+ goto CATCH;
+ }
+
+ for (i = 0 ; i <= pDcfHandler->m_DrmEndOffset ; i++)
+ {
+ nRet = pDcfHandler->DrmSeek(-i, SEEK_END);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_01 DrmSeek failed (SEEK_END, forward) : key=%d, file=%s, i=%lld, %x\n", first_key, pDCF, i, nRet);
+ goto CATCH;
+ }
+
+ DrmCurOffset = pDcfHandler->DrmTell();
+ if (DrmCurOffset != pDcfHandler->m_DrmCurOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_01 - DrmCurOffset Comparison failed (SEEK_END, forward) : origin = %lld, result = %lld, i = %%lld\n", DrmCurOffset, pDcfHandler->m_DrmCurOffset, i);
+ goto CATCH;
+ }
+ }
+ if (DrmCurOffset != 0)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_01 DrmSeek failed (SEEK_END, forward), DrmCurOffset = %lld, %x\n", DrmCurOffset, nRet);
+ goto CATCH;
+ }
+
+ for (i = pDcfHandler->m_DrmEndOffset ; i >= 0 ; i--)
+ {
+ nRet = pDcfHandler->DrmSeek(-i, SEEK_END);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_01 DrmSeek failed (SEEK_END, backward) : key=%d, file=%s, i=%lld, %x\n", first_key, pDCF, i, nRet);
+ goto CATCH;
+ }
+
+ DrmCurOffset = pDcfHandler->DrmTell();
+ if (DrmCurOffset != pDcfHandler->m_DrmCurOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_01 - DrmCurOffset Comparison failed (SEEK_END, backward) : origin = %lld, result = %lld, i = %lld\n", DrmCurOffset, pDcfHandler->m_DrmCurOffset, i);
+ goto CATCH;
+ }
+ }
+ if (DrmCurOffset != pDcfHandler->m_DrmEndOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_01 DrmSeek failed (SEEK_END, backward), DrmCurOffset = %lld, RealEndOffset = %lld, %x\n", DrmCurOffset, pDcfHandler->m_DrmEndOffset, nRet);
+ goto CATCH;
+ }
+
+ for (i = 0 ; i < pDcfHandler->m_DrmEndOffset ; i++)
+ {
+ nRet = pDcfHandler->DrmSeek(-1, SEEK_CUR);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_01 DrmSeek failed (SEEK_CUR, forward) : key=%d, file=%s, i=%lld, %x\n", first_key, pDCF, i, nRet);
+ goto CATCH;
+ }
+
+ DrmCurOffset = pDcfHandler->DrmTell();
+ if (DrmCurOffset != pDcfHandler->m_DrmCurOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_01 - DrmCurOffset Comparison failed : origin=%lld, result=%lld\n", DrmCurOffset, pDcfHandler->m_DrmCurOffset);
+ goto CATCH;
+ }
+ }
+ if (DrmCurOffset != 0)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_01 DrmSeek failed (SEEK_CUR, forward), DrmCurOffset = %lld, %x\n", DrmCurOffset, nRet);
+ goto CATCH;
+ }
+
+ for (i = 0 ; i < pDcfHandler->m_DrmEndOffset ; i++)
+ {
+ nRet = pDcfHandler->DrmSeek(1, SEEK_CUR);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_01 DrmSeek failed (SEEK_CUR, backward) : key=%d, file=%s, i=%lld, %x\n", first_key, pDCF, i, nRet);
+ goto CATCH;
+ }
+
+ DrmCurOffset = pDcfHandler->DrmTell();
+ if (DrmCurOffset != pDcfHandler->m_DrmCurOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_01 - DrmCurOffset Comparison failed (SEEK_CUR, backward) : origin = %lld, result = %lld, i = %lld\n", DrmCurOffset, pDcfHandler->m_DrmCurOffset, i);
+ goto CATCH;
+ }
+ }
+ if (DrmCurOffset != pDcfHandler->m_DrmEndOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_01 DrmSeek failed (SEEK_CUR, backward), DrmCurOffset = %lld, %x\n", DrmCurOffset, nRet);
+ goto CATCH;
+ }
+
+ printf("tc09_DrmFileMgrPositive_FileAPI_01 finished! -------- success \n");
+
+ return true;
+
+CATCH:
+ return false;
+}
+
+bool tc09_DrmFileMgrPositive_FileAPI_02(void)
+{
+ const char *pDCF = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/DCF/8SPXfqc6iL.tpk");
+ int nRet = TADC_SUCCESS;
+
+ DrmFileMgr* pDrmFileMgr = NULL;
+ DrmFileHandler *pDcfHandler = NULL;
+
+ long long originalEndOffset = 705914;
+ long long DrmCurOffset = 0;
+ long long OriginCurOffset = 842;
+ long long i = 0;
+
+ printf("tc09_DrmFileMgrPositive_FileAPI_02() -------- Started! \n");
+
+ pDrmFileMgr = DrmFileMgr::GetInstance();
+
+ nRet = pDrmFileMgr->GetFileHandler(second_key, &pDcfHandler);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_02 failed : key = %d, file = %s, %x\n", second_key, pDCF, nRet);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_OriginEndOffset != originalEndOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_02 - originalEndOffset Comparison failed : origin = %lld, result = %lld\n", originalEndOffset, pDcfHandler->m_OriginEndOffset);
+ goto CATCH;
+ }
+
+ if (OriginCurOffset != pDcfHandler->m_OriginCurOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_02 - originalCurOffset Comparison failed : origin = %lld, result = %lld\n", OriginCurOffset, pDcfHandler->m_OriginCurOffset);
+ goto CATCH;
+ }
+
+ for (i = 0 ; i <= pDcfHandler->m_DrmEndOffset ; i++)
+ {
+ nRet = pDcfHandler->DrmSeek(i, SEEK_SET);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_02 DrmSeek failed (SEEK_SET, forward) : key = %d, file = %s, i = %lld, ret = %x\n", second_key, pDCF, i, nRet);
+ goto CATCH;
+ }
+
+ DrmCurOffset = pDcfHandler->DrmTell();
+ if (DrmCurOffset != pDcfHandler->m_DrmCurOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_02 - DrmCurOffset Comparison failed (SEEK_SET, forward : origin = %lld, result = %lld, i = %lld\n", DrmCurOffset, pDcfHandler->m_DrmCurOffset, i);
+ goto CATCH;
+ }
+ }
+ if (DrmCurOffset != pDcfHandler->m_DrmEndOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_02 DrmSeek failed (SEEK_SET, forward), DrmCurOffset = %lld, RealEndOffset = %lld, %x\n", DrmCurOffset, pDcfHandler->m_DrmEndOffset, nRet);
+ goto CATCH;
+ }
+
+ for (i = pDcfHandler->m_DrmEndOffset ; i >= 0 ; i--)
+ {
+ nRet = pDcfHandler->DrmSeek(i, SEEK_SET);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_02 DrmSeek failed (SEEK_SET, backward) : key=%d, file=%s, i=%lld, %x\n", second_key, pDCF, i, nRet);
+ goto CATCH;
+ }
+
+ DrmCurOffset = pDcfHandler->DrmTell();
+ if (DrmCurOffset != pDcfHandler->m_DrmCurOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_02 - DrmCurOffset Comparison failed (SEEK_SET, backward) : origin = %lld, result = %lld, i = %lld\n", DrmCurOffset, pDcfHandler->m_DrmCurOffset, i);
+ goto CATCH;
+ }
+ }
+ if (DrmCurOffset != 0)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_02 DrmSeek failed (SEEK_SET, backward), DrmCurOffset = %lld, %x\n", DrmCurOffset, nRet);
+ goto CATCH;
+ }
+
+ for (i = 0 ; i <= pDcfHandler->m_DrmEndOffset ; i++)
+ {
+ nRet = pDcfHandler->DrmSeek(-i, SEEK_END);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_02 DrmSeek failed (SEEK_END, forward) : key=%d, file=%s, i=%lld, %x\n", second_key, pDCF, i, nRet);
+ goto CATCH;
+ }
+
+ DrmCurOffset = pDcfHandler->DrmTell();
+ if (DrmCurOffset != pDcfHandler->m_DrmCurOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_02 - DrmCurOffset Comparison failed (SEEK_END, forward) : origin = %lld, result = %lld, i = %lld\n", DrmCurOffset, pDcfHandler->m_DrmCurOffset, i);
+ goto CATCH;
+ }
+ }
+ if (DrmCurOffset != 0)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_02 DrmSeek failed (SEEK_END, forward), DrmCurOffset = %lld, %x\n", DrmCurOffset, nRet);
+ goto CATCH;
+ }
+
+ for (i = pDcfHandler->m_DrmEndOffset ; i >= 0 ; i--)
+ {
+ nRet = pDcfHandler->DrmSeek(-i, SEEK_END);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_02 DrmSeek failed (SEEK_END, backward) : key=%d, file=%s, i=%lld, %x\n", second_key, pDCF, i, nRet);
+ goto CATCH;
+ }
+
+ DrmCurOffset = pDcfHandler->DrmTell();
+ if (DrmCurOffset != pDcfHandler->m_DrmCurOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_02 - DrmCurOffset Comparison failed (SEEK_END, backward) : origin = %lld, result = %lld, i = %lld\n", DrmCurOffset, pDcfHandler->m_DrmCurOffset, i);
+ goto CATCH;
+ }
+ }
+ if (DrmCurOffset != pDcfHandler->m_DrmEndOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_02 DrmSeek failed (SEEK_END, backward), DrmCurOffset = %lld, RealEndOffset = %lld, %x\n", DrmCurOffset, pDcfHandler->m_DrmEndOffset, nRet);
+ goto CATCH;
+ }
+
+ for (i = 0 ; i < pDcfHandler->m_DrmEndOffset ; i++)
+ {
+ nRet = pDcfHandler->DrmSeek(-1, SEEK_CUR);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_02 DrmSeek failed (SEEK_CUR, forward) : key=%d, file=%s, i=%lld, %x\n", second_key, pDCF, i, nRet);
+ goto CATCH;
+ }
+
+ DrmCurOffset = pDcfHandler->DrmTell();
+ if (DrmCurOffset != pDcfHandler->m_DrmCurOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_02 - DrmCurOffset Comparison failed : origin=%lld, result=%lld\n", DrmCurOffset, pDcfHandler->m_DrmCurOffset);
+ goto CATCH;
+ }
+ }
+ if (DrmCurOffset != 0)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_02 DrmSeek failed (SEEK_CUR, forward), DrmCurOffset = %lld, %x\n", DrmCurOffset, nRet);
+ goto CATCH;
+ }
+
+ for (i = 0 ; i < pDcfHandler->m_DrmEndOffset ; i++)
+ {
+ nRet = pDcfHandler->DrmSeek(1, SEEK_CUR);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_02 DrmSeek failed (SEEK_CUR, backward) : key=%d, file=%s, i=%lld, %x\n", second_key, pDCF, i, nRet);
+ goto CATCH;
+ }
+
+ DrmCurOffset = pDcfHandler->DrmTell();
+ if (DrmCurOffset != pDcfHandler->m_DrmCurOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_02 - DrmCurOffset Comparison failed (SEEK_CUR, backward) : origin = %lld, result = %lld, i = %lld\n", DrmCurOffset, pDcfHandler->m_DrmCurOffset, i);
+ goto CATCH;
+ }
+ }
+ if (DrmCurOffset != pDcfHandler->m_DrmEndOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_02 DrmSeek failed (SEEK_CUR, backward), DrmCurOffset = %lld, %x\n", DrmCurOffset, nRet);
+ goto CATCH;
+ }
+
+ printf("tc09_DrmFileMgrPositive_FileAPI_02 finished! -------- success \n");
+
+ return true;
+
+CATCH:
+ return false;
+}
+
+bool tc09_DrmFileMgrPositive_FileAPI_03(void)
+{
+ const char *pDCF = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/DCF/FightGuiIF.tpk");
+ int nRet = TADC_SUCCESS;
+
+ DrmFileMgr* pDrmFileMgr = NULL;
+ DrmFileHandler *pDcfHandler = NULL;
+
+ long long originalEndOffset = 45194636;
+ long long DrmCurOffset = 0;
+ long long OriginCurOffset = 847;
+ long long i = 0;
+
+ printf("tc09_DrmFileMgrPositive_FileAPI_03() -------- Started! \n");
+
+ pDrmFileMgr = DrmFileMgr::GetInstance();
+
+ nRet = pDrmFileMgr->GetFileHandler(third_key, &pDcfHandler);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 failed : key = %d, file = %s, %x\n", third_key, pDCF, nRet);
+ goto CATCH;
+ }
+
+ if (pDcfHandler->m_OriginEndOffset != originalEndOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 - originalEndOffset Comparison failed : origin = %lld, result = %lld\n", originalEndOffset, pDcfHandler->m_OriginEndOffset);
+ goto CATCH;
+ }
+
+ if (OriginCurOffset != pDcfHandler->m_OriginCurOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 - originalCurOffset Comparison failed : origin = %lld, result = %lld\n", OriginCurOffset, pDcfHandler->m_OriginCurOffset);
+ goto CATCH;
+ }
+
+ for (i = 0 ; i <= pDcfHandler->m_DrmEndOffset ; i++)
+ {
+ nRet = pDcfHandler->DrmSeek(i, SEEK_SET);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 DrmSeek failed (SEEK_SET, forward) : key = %d, file = %s, i = %lld, ret = %x\n", third_key, pDCF, i, nRet);
+ goto CATCH;
+ }
+
+ DrmCurOffset = pDcfHandler->DrmTell();
+ if (DrmCurOffset != pDcfHandler->m_DrmCurOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 - DrmCurOffset Comparison failed (SEEK_SET, forward) : origin = %lld, result = %lld, i = %lld\n", DrmCurOffset, pDcfHandler->m_DrmCurOffset, i);
+ goto CATCH;
+ }
+ }
+ if (DrmCurOffset != pDcfHandler->m_DrmEndOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 DrmSeek failed (SEEK_SET, forward), DrmCurOffset = %lld, RealEndOffset = %lld, %x\n", DrmCurOffset, pDcfHandler->m_DrmEndOffset, nRet);
+ goto CATCH;
+ }
+
+ for (i = pDcfHandler->m_DrmEndOffset ; i >= 0 ; i--)
+ {
+ nRet = pDcfHandler->DrmSeek(i, SEEK_SET);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 DrmSeek failed (SEEK_SET, backward) : key=%d, file=%s, i=%lld, %x\n", third_key, pDCF, i, nRet);
+ goto CATCH;
+ }
+
+ DrmCurOffset = pDcfHandler->DrmTell();
+ if (DrmCurOffset != pDcfHandler->m_DrmCurOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 - DrmCurOffset Comparison failed (SEEK_SET, backward) : origin = %lld, result = %lld, i = %lld\n", DrmCurOffset, pDcfHandler->m_DrmCurOffset, i);
+ goto CATCH;
+ }
+ }
+ if (DrmCurOffset != 0)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 DrmSeek failed (SEEK_SET, backward), DrmCurOffset = %lld, %x\n", DrmCurOffset, nRet);
+ goto CATCH;
+ }
+
+ for (i = 0 ; i <= pDcfHandler->m_DrmEndOffset ; i++)
+ {
+ nRet = pDcfHandler->DrmSeek(-i, SEEK_END);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 DrmSeek failed (SEEK_END, forward) : key=%d, file=%s, i=%lld, %x\n", third_key, pDCF, i, nRet);
+ goto CATCH;
+ }
+
+ DrmCurOffset = pDcfHandler->DrmTell();
+ if (DrmCurOffset != pDcfHandler->m_DrmCurOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 - DrmCurOffset Comparison failed (SEEK_END, forward) : origin = %lld, result = %lld, i = %lld\n", DrmCurOffset, pDcfHandler->m_DrmCurOffset, i);
+ goto CATCH;
+ }
+ }
+ if (DrmCurOffset != 0)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 DrmSeek failed (SEEK_END, forward), DrmCurOffset = %lld, %x\n", DrmCurOffset, nRet);
+ goto CATCH;
+ }
+
+ for (i = pDcfHandler->m_DrmEndOffset ; i >= 0 ; i--)
+ {
+ nRet = pDcfHandler->DrmSeek(-i, SEEK_END);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 DrmSeek failed (SEEK_END, backward) : key=%d, file=%s, i=%lld, %x\n", third_key, pDCF, i, nRet);
+ goto CATCH;
+ }
+
+ DrmCurOffset = pDcfHandler->DrmTell();
+ if (DrmCurOffset != pDcfHandler->m_DrmCurOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 - DrmCurOffset Comparison failed (SEEK_END, backward) : origin = %lld, result = %lld, i = %lld\n", DrmCurOffset, pDcfHandler->m_DrmCurOffset, i);
+ goto CATCH;
+ }
+ }
+ if (DrmCurOffset != pDcfHandler->m_DrmEndOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 DrmSeek failed (SEEK_END, backward), DrmCurOffset = %lld, RealEndOffset = %lld, %x\n", DrmCurOffset, pDcfHandler->m_DrmEndOffset, nRet);
+ goto CATCH;
+ }
+
+ for (i = 0 ; i < pDcfHandler->m_DrmEndOffset ; i++)
+ {
+ nRet = pDcfHandler->DrmSeek(-1, SEEK_CUR);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 DrmSeek failed (SEEK_CUR, forward) : key=%d, file=%s, i=%lld, %x\n", third_key, pDCF, i, nRet);
+ goto CATCH;
+ }
+
+ DrmCurOffset = pDcfHandler->DrmTell();
+ if (DrmCurOffset != pDcfHandler->m_DrmCurOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 - DrmCurOffset Comparison failed : origin=%lld, result=%lld\n", DrmCurOffset, pDcfHandler->m_DrmCurOffset);
+ goto CATCH;
+ }
+ }
+ if (DrmCurOffset != 0)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 DrmSeek failed (SEEK_CUR, forward), DrmCurOffset = %lld, %x\n", DrmCurOffset, nRet);
+ goto CATCH;
+ }
+
+ for (i = 0 ; i < pDcfHandler->m_DrmEndOffset ; i++)
+ {
+ nRet = pDcfHandler->DrmSeek(1, SEEK_CUR);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 DrmSeek failed (SEEK_CUR, backward) : key=%d, file=%s, i=%lld, %x\n", third_key, pDCF, i, nRet);
+ goto CATCH;
+ }
+
+ DrmCurOffset = pDcfHandler->DrmTell();
+ if (DrmCurOffset != pDcfHandler->m_DrmCurOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 - DrmCurOffset Comparison failed (SEEK_CUR, backward) : origin = %lld, result = %lld, i = %lld\n", DrmCurOffset, pDcfHandler->m_DrmCurOffset, i);
+ goto CATCH;
+ }
+ }
+ if (DrmCurOffset != pDcfHandler->m_DrmEndOffset)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 DrmSeek failed (SEEK_CUR, backward), DrmCurOffset = %lld, %x\n", DrmCurOffset, nRet);
+ goto CATCH;
+ }
+
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 finished! -------- success \n");
+
+ return true;
+
+CATCH:
+ return false;
+}
+
+bool tc10_DrmFileMgrPositive_CloseFileHandler_01(void)
+{
+ int nRet = TADC_SUCCESS;
+
+ DrmFileMgr* pDrmFileMgr = NULL;
+ DrmFileHandler *pDcfHandler = NULL;
+
+ printf("tc10_DrmFileMgrPositive_CloseFileHandler_01 -------- Started! \n");
+
+ pDrmFileMgr = DrmFileMgr::GetInstance();
+
+ nRet = pDrmFileMgr->GetFileHandler(first_key, &pDcfHandler);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc10_DrmFileMgrPositive_CloseFileHandler_01 failed : key = %d, ret=%x\n", first_key, nRet);
+ goto CATCH;
+ }
+
+ nRet = pDrmFileMgr->CloseFileHandler(first_key);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc10_DrmFileMgrPositive_CloseFileHandler_01 failed : key = %d, ret=%x\n", first_key, nRet);
+ goto CATCH;
+ }
+
+ nRet = pDrmFileMgr->GetFileHandler(first_key, &pDcfHandler);
+ if (nRet == TADC_SUCCESS)
+ {
+ printf("tc10_DrmFileMgrPositive_CloseFileHandler_01 failed : key = %d\n", first_key);
+ goto CATCH;
+ }
+
+ printf("tc10_DrmFileMgrPositive_CloseFileHandler_01 finished! -------- success \n");
+
+ return true;
+
+CATCH:
+ return false;
+}
+
+bool tc10_DrmFileMgrPositive_CloseFileHandler_02(void)
+{
+ int nRet = TADC_SUCCESS;
+
+ DrmFileMgr* pDrmFileMgr = NULL;
+ DrmFileHandler *pDcfHandler = NULL;
+
+ printf("tc10_DrmFileMgrPositive_CloseFileHandler_02 -------- Started! \n");
+
+ pDrmFileMgr = DrmFileMgr::GetInstance();
+
+ nRet = pDrmFileMgr->GetFileHandler(second_key, &pDcfHandler);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc10_DrmFileMgrPositive_CloseFileHandler_02 failed : key = %d, ret=%x\n", second_key, nRet);
+ goto CATCH;
+ }
+
+ nRet = pDrmFileMgr->CloseFileHandler(second_key);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc10_DrmFileMgrPositive_CloseFileHandler_02 failed : key = %d, ret=%x\n", second_key, nRet);
+ goto CATCH;
+ }
+
+ nRet = pDrmFileMgr->GetFileHandler(second_key, &pDcfHandler);
+ if (nRet == TADC_SUCCESS)
+ {
+ printf("tc10_DrmFileMgrPositive_CloseFileHandler_02 failed : key = %d\n", second_key);
+ goto CATCH;
+ }
+
+ printf("tc10_DrmFileMgrPositive_CloseFileHandler_02 finished! -------- success \n");
+
+ return true;
+
+CATCH:
+ return false;
+}
+
+bool tc10_DrmFileMgrPositive_CloseFileHandler_03(void)
+{
+ int nRet = TADC_SUCCESS;
+
+ DrmFileMgr* pDrmFileMgr = NULL;
+ DrmFileHandler *pDcfHandler = NULL;
+
+ printf("tc10_DrmFileMgrPositive_CloseFileHandler_03 -------- Started! \n");
+
+ pDrmFileMgr = DrmFileMgr::GetInstance();
+
+ nRet = pDrmFileMgr->GetFileHandler(third_key, &pDcfHandler);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc10_DrmFileMgrPositive_CloseFileHandler_03 failed : key = %d, ret=%x\n", third_key, nRet);
+ goto CATCH;
+ }
+
+ nRet = pDrmFileMgr->CloseFileHandler(third_key);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc10_DrmFileMgrPositive_CloseFileHandler_03 failed : key = %d, ret=%x\n", third_key, nRet);
+ goto CATCH;
+ }
+
+ nRet = pDrmFileMgr->GetFileHandler(third_key, &pDcfHandler);
+ if (nRet == TADC_SUCCESS)
+ {
+ printf("tc10_DrmFileMgrPositive_CloseFileHandler_03 failed : key = %d\n", third_key);
+ goto CATCH;
+ }
+
+ printf("tc10_DrmFileMgrPositive_CloseFileHandler_03 finished! -------- success \n");
+
+ return true;
+
+CATCH:
+ return false;
+}
+
+bool tc11_GetDeviceId_01(void)
+{
+ unsigned char DUID[33] = {0,};
+ int nRet = 0;
+
+ printf("tc11_GetDeviceID_01() -------- Started! \n");
+
+ nRet = TADC_IF_GetDUID((char*)DUID);
+ if (nRet !=TADC_SUCCESS)
+ {
+ printf("tc11_GetDeviceID_01() failed.");
+ return false;
+ }
+
+ printf("DUID=%s\n", (char*)DUID);
+ printf("tc11_GetDeviceID_01() finished! -------- success \n");
+
+ return true;
+}
+
+bool tc12_TADC_SetDeviceInfo_01(void)
+{
+ int nRet = TADC_SUCCESS;
+ T_DEVICE_INFO t_DeviceInfo;
+
+ printf("tc12_TADC_SetDeviceInfo_01() -------- Started! \n");
+
+ nRet = TADC_SetDeviceInfo(&t_DeviceInfo);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc12_TADC_SetDeviceInfo_01() failed.\n");
+ return false;
+ }
+ printf("DUID=%s\n", (char*)t_DeviceInfo.DUID);
+ printf("tc12_TADC_SetDeviceInfo_01() finished! -------- success \n");
+
+ return true;
+}
+
+bool
+tc13_DTappsInstallLicense_01(void)
+{
+ int nRet = TADC_SUCCESS;
+ char Buf[1024*10] = {0, };
+ const char *pFirstRo = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/RO/38EIfBurLJ-1.0.2.ro");
+ FILE* fd = NULL;
+ int nReadLen = 0;
+ long lSize = 0;
+ bool res = true;
+
+ printf("tc13_DTappsInstallLicense_01() -------- Started! \n");
+
+ fd = fopen(pFirstRo, "rb");
+ if (fd == NULL)
+ {
+ printf("File is not exist! : %s\n", pFirstRo);
+ res = false;
+ goto CATCH;
+ }
+
+ fseek(fd, 0, SEEK_END);
+ lSize = ftell(fd);
+ if (lSize < 0)
+ {
+ printf("fseek() and ftell() failed.");
+ res = false;
+ goto CATCH;
+ }
+ rewind(fd);
+
+ memset(Buf, 0x00, sizeof(Buf));
+ nReadLen = fread(Buf, 1, lSize, fd);
+ if (nReadLen >= sizeof(Buf))
+ {
+ printf("Buffer error! : %s\n", pFirstRo);
+ goto CATCH;
+ }
+
+ if (nReadLen != lSize)
+ {
+ printf("File read error! : %s\n", pFirstRo);
+ res = false;
+ goto CATCH;
+ }
+
+ nRet = DTappsInstallLicense(Buf);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc13_DTappsInstallLicense_01() failed. nRet=%d\n", nRet);
+ res = false;
+ goto CATCH;
+ }
+
+ printf("tc13_DTappsInstallLicense_01() finished! -------- success \n");
+
+CATCH:
+ if (fd != NULL)
+ {
+ fclose(fd);
+ }
+ return res;
+}
+
+bool
+tc13_DTappsInstallLicense_02(void)
+{
+ int nRet = TADC_SUCCESS;
+ char Buf[1024*10] = {0, };
+ const char *pFirstRo = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/RO/8SPXfqc6iL-1.0.0.ro");
+ FILE* fd = NULL;
+ int nReadLen = 0;
+ long lSize = 0;
+ bool res = true;
+
+ printf("tc13_DTappsInstallLicense_02() -------- Started! \n");
+
+ fd = fopen(pFirstRo, "rb");
+ if (fd == NULL)
+ {
+ printf("File is not exist! : %s\n", pFirstRo);
+ res = false;
+ goto CATCH;
+ }
+
+ fseek(fd, 0, SEEK_END);
+ lSize = ftell(fd);
+ if (lSize < 0)
+ {
+ printf("fseek() and ftell() failed.");
+ res = false;
+ goto CATCH;
+ }
+ rewind(fd);
+
+ memset(Buf, 0x00, sizeof(Buf));
+ nReadLen = fread(Buf, 1, lSize, fd);
+ if (nReadLen >= sizeof(Buf))
+ {
+ printf("Buffer error! : %s\n", pFirstRo);
+ goto CATCH;
+ }
+
+ if (nReadLen != lSize)
+ {
+ printf("File read error! : %s\n", pFirstRo);
+ res = false;
+ goto CATCH;
+ }
+
+ nRet = DTappsInstallLicense(Buf);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc13_DTappsInstallLicense_02() failed. nRet=%d\n", nRet);
+ res = false;
+ goto CATCH;
+ }
+
+ printf("tc13_DTappsInstallLicense_02() finished! -------- success \n");
+
+CATCH:
+ if (fd != NULL)
+ {
+ fclose(fd);
+ }
+ return res;
+}
+
+bool
+tc13_DTappsInstallLicense_03(void)
+{
+ int nRet = TADC_SUCCESS;
+ char Buf[1024*10] = {0, };
+ const char *pFirstRo = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/RO/FightGuiIF-1.0.0.ro");
+ FILE* fd = NULL;
+ int nReadLen = 0;
+ long lSize = 0;
+ bool res = true;
+
+ printf("tc13_DTappsInstallLicense_03() -------- Started! \n");
+
+ fd = fopen(pFirstRo, "rb");
+ if (fd == NULL)
+ {
+ printf("File is not exist! : %s\n", pFirstRo);
+ res = false;
+ goto CATCH;
+ }
+
+ fseek(fd, 0, SEEK_END);
+ lSize = ftell(fd);
+ if (lSize < 0)
+ {
+ printf("fseek() and ftell() failed.");
+ res = false;
+ goto CATCH;
+ }
+ rewind(fd);
+
+ memset(Buf, 0x00, sizeof(Buf));
+ nReadLen = fread(Buf, 1, lSize, fd);
+ if (nReadLen >= sizeof(Buf))
+ {
+ printf("Buffer error! : %s\n", pFirstRo);
+ goto CATCH;
+ }
+
+ if (nReadLen != lSize)
+ {
+ printf("File read error! : %s\n", pFirstRo);
+ res = false;
+ goto CATCH;
+ }
+
+ nRet = DTappsInstallLicense(Buf);
+ if (nRet != TADC_SUCCESS)
+ {
+ printf("tc13_DTappsInstallLicense_03() failed. nRet=%d\n", nRet);
+ res = false;
+ goto CATCH;
+ }
+
+ printf("tc13_DTappsInstallLicense_03() finished! -------- success \n");
+
+CATCH:
+ if (fd != NULL)
+ {
+ fclose(fd);
+ }
+ return res;
+}
+
+bool
+tc_local_01_drm_tizen_generate_license_request_p(void)
+{
+ bool res = true;
+ int ret_value = DRMTEST_SUCCESS;
+
+ char *purchase_response = NULL;
+ char *req_id = NULL;
+ unsigned int req_buff_len = 1024*5;
+ char req_buff[req_buff_len] = {0, };
+ unsigned int url_buff_len = 1024;
+ char url_buff[url_buff_len] = {0, };
+
+ printf("[%s] test started\n", __func__);
+ ret_value = generate_purchase_response(&purchase_response, &req_id);
+ if(ret_value != DRMTEST_SUCCESS) {
+ res = false;
+ goto CATCH;
+ }
+ printf("...purchase_response:\n%s\n", purchase_response);
+
+ ret_value = drm_tizen_generate_license_request(purchase_response, strlen(purchase_response),
+ req_buff, &req_buff_len, url_buff, &url_buff_len);
+ if(ret_value != TADC_SUCCESS) {
+ printf("...drm_tizen_generate_license_request failed. ret=%d\n", ret_value);
+ res = false;
+ goto CATCH;
+ }
+ printf("...license_request_url:%s\n", url_buff);
+ printf("...license_request:\n%s\n", req_buff);
+
+ printf("[%s] test ended: result=%d\n", __func__, ret_value);
+
+CATCH:
+ if(purchase_response != NULL)
+ free(purchase_response);
+ if(req_id != NULL)
+ free(req_id);
+
+ return res;
+}
+
+bool
+tc_local_01_drm_tizen_full_test_p(void)
+{
+ bool res = true;
+ int ret_value = DRMTEST_SUCCESS;
+
+ char *purchase_response = NULL;
+ char *req_id = NULL;
+ unsigned int req_buff_len = 1024*5;
+ char req_buff[req_buff_len] = {0, };
+ unsigned int url_buff_len = 1024;
+ char url_buff[url_buff_len] = {0, };
+
+ char* ro_request_buff = NULL;
+ char* ro_response_buff = NULL;
+ char* dh_key_p = NULL;
+ char* dh_key_g = NULL;
+ char* dh_key_a = NULL;
+
+ unsigned char duid[33] = {0,};
+ const char* cid = "38EIfBurLJ-1.0.2";
+ const char* ro_template_path = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/RO/38EIfBurLJ-1.0.2.ro_template");
+
+ const char* encrypted_file_path = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/DCF/38EIfBurLJ.tpk");
+ const char* plaintext_file_path = tzplatform_mkpath(TZ_SYS_DATA,"drm_test/DecryptedApp/38EIfBurLJ_dec.tpk");
+ const char* decrypted_file_path = "/tmp/38EIfBurLJ.tpk";
+
+ int identical = DRMTEST_NOTIDENTICAL;
+
+ printf("[%s] test started\n", __func__);
+
+ if(ret_value != DRMTEST_SUCCESS) {
+ res = false;
+ goto CATCH;
+ }
+
+ ret_value = generate_purchase_response(&purchase_response, &req_id);
+ if(ret_value != DRMTEST_SUCCESS) {
+ res = false;
+ goto CATCH;
+ }
+ //printf("...purchase_response:\n%s\n", purchase_response);
+
+ ret_value = drm_tizen_generate_license_request(purchase_response, strlen(purchase_response),
+ req_buff, &req_buff_len, url_buff, &url_buff_len);
+ if(ret_value != TADC_SUCCESS) {
+ printf("...drm_tizen_generate_license_request failed. ret=%d\n", ret_value);
+ res = false;
+ goto CATCH;
+ }
+ printf("...license_request_url:%s\n", url_buff);
+ printf("...license_request:\n%s\n", req_buff);
+
+ ret_value = get_dh_key_from_ro_request(req_buff, &dh_key_p, &dh_key_g, &dh_key_a);
+ if(ret_value != DRMTEST_SUCCESS) {
+ res = false;
+ goto CATCH;
+ }
+ //printf("...DH key: p=%s, g=%s, a=%s\n", dh_key_p, dh_key_g, dh_key_a);
+
+ ret_value = TADC_IF_GetDUID((char*)duid);
+ if (ret_value != TADC_SUCCESS) {
+ return false;
+ }
+ printf("duid=%s\n", (char*)duid);
+
+ ret_value = generate_right_object_response(dh_key_p, dh_key_g, dh_key_a, req_id,
+ cid, ro_template_path, (const char*)duid, &ro_response_buff);
+ if(ret_value != DRMTEST_SUCCESS) {
+ res = false;
+ goto CATCH;
+ }
+ printf("...right_object_response:\n%s\n", ro_response_buff);
+
+ ret_value = drm_tizen_register_license(ro_response_buff, strlen(ro_response_buff));
+ if(ret_value != TADC_SUCCESS) {
+ printf("...drm_tizen_register_license failed. ret=%d\n", ret_value);
+ res = false;
+ goto CATCH;
+ }
+ printf("...drm_tizen_register_license: succeeded\n");
+
+ ret_value = drm_tizen_decrypt_package(encrypted_file_path, strlen(encrypted_file_path),
+ decrypted_file_path, strlen(decrypted_file_path));
+ if(ret_value != TADC_SUCCESS) {
+ printf("...drm_tizen_decrypt_package failed. ret=%d\n", ret_value);
+ res = false;
+ goto CATCH;
+ }
+ printf("...drm_tizen_decrypt_package: succeeded\n");
+
+ ret_value = is_identical_files(plaintext_file_path, decrypted_file_path, &identical);
+ if(ret_value != DRMTEST_SUCCESS) {
+ printf("...is_identical_files failed. ret=%d\n", ret_value);
+ res = false;
+ goto CATCH;
+ }
+ if(identical != DRMTEST_IDENTICAL) {
+ printf("...the decrypted file is not same with a original plaintext file .\n");
+ res = false;
+ goto CATCH;
+ }
+ printf("...drm_tizen_decrypt_package: succeeded : the decrypted file is with a original plaintext file.\n");
+
+CATCH:
+ if(purchase_response != NULL)
+ free(purchase_response);
+ if(req_id != NULL)
+ free(req_id);
+ if(ro_request_buff != NULL)
+ free(ro_request_buff);
+ if(ro_response_buff != NULL)
+ free(ro_response_buff);
+
+ return res;
+}
+
+
+/*
+bool tc15_DrmTdcDecryptPackge_01(void)
+{
+ int nRet = TADC_SUCCESS;
+
+}
+*/
+#endif
+
+int main(int argc, char* argv[])
+{
+// return 0;
+#if 1
+ printf(" ---------- Test Tizen DRM v2.0.1 APIs --- Start .... \n");
+
+ int bRet = TADC_SUCCESS;
+
+ char ReqBuf[1024*5] = {0, };
+ unsigned int ReqBufLen = 0;
+
+ char RespBuf[1024*10] = {0, };
+ unsigned int RespBufLen = 0;
+
+// char DecLicenseBuf[1024*10] = {0, };
+// unsigned int DecLicenseBufLen = 0;
+
+ char LicenseUrl[1024] = {0, };
+ unsigned int LicenseUrlLen = 0;
+
+ //2011.03.08
+ //DrmTdcFileHeader TDCFileHeader;
+// char cid[1024] = {0, };
+// char riurl[1024] = {0, };
+
+ char testFileName[256] = {0, };
+ char tempBuf[256] = {0, };
+
+ bool isOk = false;
+
+ //----------------------------------------------------------------------------------------------------
+ // 0. Static TC running
+ //----------------------------------------------------------------------------------------------------
+
+ printf("\n0. Static TC Start ----------------------------------------\n");
+/*
+ isOk = tc01_VerifyRoSignature_Positive_01();
+ if (isOk != true)
+ {
+ printf("tc01_VerifyRoSignature_Positive_01 failed!\n");
+ }
+
+ isOk = tc01_VerifyRoSignature_Positive_02();
+ if (isOk != true)
+ {
+ printf("tc01_VerifyRoSignature_Positive_02 failed!\n");
+ }
+
+ isOk = tc01_VerifyRoSignature_Positive_03();
+ if (isOk != true)
+ {
+ printf("tc01_VerifyRoSignature_Positive_03 failed!\n");
+ }
+
+ isOk = tc02_VerifyRoSignature_Negative_Cert_01();
+ if (isOk != true)
+ {
+ printf("tc02_VerifyRoSignature_Negative_Cert_01 failed!\n");
+ }
+
+ isOk = tc02_VerifyRoSignature_Negative_Cert_02();
+ if (isOk != true)
+ {
+ printf("tc02_VerifyRoSignature_Negative_Cert_02 failed!\n");
+ }
+
+ isOk = tc02_VerifyRoSignature_Negative_Cert_03();
+ if (isOk != true)
+ {
+ printf("tc02_VerifyRoSignature_Negative_Cert_03 failed!\n");
+ }
+
+ isOk = tc03_VerifyRoSignature_Negative_Signature_01();
+ if (isOk != true)
+ {
+ printf("tc03_VerifyRoSignature_Negative_Signature_01 failed!\n");
+ }
+
+ isOk = tc03_VerifyRoSignature_Negative_Signature_02();
+ if (isOk != true)
+ {
+ printf("tc03_VerifyRoSignature_Negative_Signature_02 failed!\n");
+ }
+
+ isOk = tc03_VerifyRoSignature_Negative_Signature_03();
+ if (isOk != true)
+ {
+ printf("tc03_VerifyRoSignature_Negative_Signature_03 failed!\n");
+ }
+
+ isOk = tc04_isDrmFile_Positive_01();
+ if (isOk != true)
+ {
+ printf("tc04_isDrmFile_Positive_01 failed!\n");
+ }
+
+ isOk = tc04_isDrmFile_Positive_02();
+ if (isOk != true)
+ {
+ printf("tc04_isDrmFile_Positive_02 failed!\n");
+ }
+
+ isOk = tc04_isDrmFile_Positive_03();
+ if (isOk != true)
+ {
+ printf("tc04_isDrmFile_Positive_03 failed!\n");
+ }
+
+ isOk = tc05_isDrmFile_Negative_01();
+ if (isOk != true)
+ {
+ printf("tc05_isDrmFile_Negative_01 failed!\n");
+ }
+
+ isOk = tc05_isDrmFile_Negative_02();
+ if (isOk != true)
+ {
+ printf("tc05_isDrmFile_Negative_02 failed!\n");
+ }
+
+ isOk = tc05_isDrmFile_Negative_03();
+ if (isOk != true)
+ {
+ printf("tc05_isDrmFile_Negative_03 failed!\n");
+ }
+
+ isOk = tc13_DTappsInstallLicense_01();
+ if (isOk != true)
+ {
+ printf("tc13_DTappsInstallLicense_01 failed!\n");
+ }
+
+ isOk = tc13_DTappsInstallLicense_02();
+ if (isOk != true)
+ {
+ printf("tc13_DTappsInstallLicense_02 failed!\n");
+ }
+
+ isOk = tc13_DTappsInstallLicense_03();
+ if (isOk != true)
+ {
+ printf("tc13_DTappsInstallLicense_03 failed!\n");
+ }
+
+ isOk = tc06_DrmFileHandlerPositive_01();
+ if (isOk != true)
+ {
+ printf("tc06_DrmFileHandlerPositive_01 failed!\n");
+ }
+
+ isOk = tc06_DrmFileHandlerPositive_02();
+ if (isOk != true)
+ {
+ printf("tc06_DrmFileHandlerPositive_02 failed!\n");
+ }
+
+ isOk = tc06_DrmFileHandlerPositive_03();
+ if (isOk != true)
+ {
+ printf("tc06_DrmFileHandlerPositive_03 failed!\n");
+ }
+
+ isOk = tc07_DrmFileMgrPositive_01();
+ if (isOk != true)
+ {
+ printf("tc07_DrmFileMgrPositive_01 failed!\b");
+ }
+
+ isOk = tc07_DrmFileMgrPositive_02();
+ if (isOk != true)
+ {
+ printf("tc07_DrmFileMgrPositive_02 failed!\n");
+ }
+
+ isOk = tc07_DrmFileMgrPositive_03();
+ if (isOk != true)
+ {
+ printf("tc07_DrmFileMgrPositive_03 failed!\n");
+ }
+
+ isOk = tc08_DrmFileMgrPositive_GetFileHandler_01();
+ if (isOk != true)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_01 failed!\n");
+ }
+
+ isOk = tc08_DrmFileMgrPositive_GetFileHandler_02();
+ if (isOk != true)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_02 failed!\n");
+ }
+
+ isOk = tc08_DrmFileMgrPositive_GetFileHandler_03();
+ if (isOk != true)
+ {
+ printf("tc08_DrmFileMgrPositive_GetFileHandler_03 failed!\n");
+ }
+
+ isOk = tc09_DrmFileMgrPositive_FileAPI_01();
+ if (isOk != true)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_01 failed!\n");
+ }
+
+ isOk = tc09_DrmFileMgrPositive_FileAPI_02();
+ if (isOk != true)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_02 failed!\n");
+ }
+
+ isOk = tc09_DrmFileMgrPositive_FileAPI_03();
+ if (isOk != true)
+ {
+ printf("tc09_DrmFileMgrPositive_FileAPI_03 failed!\n");
+ }
+
+ isOk = tc10_DrmFileMgrPositive_CloseFileHandler_01();
+ if (isOk != true)
+ {
+ printf("tc10_DrmFileMgrPositive_CloseFileHandler_01 failed!\n");
+ }
+
+ isOk = tc10_DrmFileMgrPositive_CloseFileHandler_02();
+ if (isOk != true)
+ {
+ printf("tc10_DrmFileMgrPositive_CloseFileHandler_02 failed!\n");
+ }
+
+ isOk = tc10_DrmFileMgrPositive_CloseFileHandler_03();
+ if (isOk != true)
+ {
+ printf("tc10_DrmFileMgrPositive_CloseFileHandler_03 failed!\n");
+ }
+
+ isOk = tc11_GetDeviceId_01();
+ if (isOk != true)
+ {
+ printf("tc11_GetDeviceId_01 failed!\n");
+ }
+
+ isOk = tc12_TADC_SetDeviceInfo_01();
+ if (isOk != true)
+ {
+ printf("tc12_TADC_SetDeviceInfo_01 failed!\n");
+ }
+
+ isOk = tc11_GetDeviceId_01();
+ if (isOk != true)
+ {
+ printf("tc11_GetDeviceId_01 failed!\n");
+ }
+*/
+ isOk = tc_local_01_drm_tizen_full_test_p();
+ if (isOk != true)
+ {
+ printf("tc_local_01_drm_tizen_full_test_p failed!\n");
+ }
+
+ //----------------------------------------------------------------------------------------------------
+ // 1. Check is drm file
+ //----------------------------------------------------------------------------------------------------
+
+ printf("===============================================================================\n");
+ printf ("Enter test file name --> ");
+
+ isOk = scanf("%s", testFileName);
+ if (isOk < 1)
+ {
+ printf ("Input value wrong! scanf() failed!!");
+ return 0;
+ }
+ printf("\n1. drm_tizen_is_drm_file Start ----------------------------------------\n");
+
+ bRet = drm_tizen_is_drm_file(testFileName, strlen(testFileName));
+ if (bRet != TADC_SUCCESS)
+ {
+ printf("drm_tizen_is_drm_file Error! ret = %d\n", bRet);
+ return 0;
+ }
+ printf("%s file is TADC file!\n", testFileName);
+
+ //----------------------------------------------------------------------------------------------------
+ // 2. Make PurchaseRequest Data
+ //----------------------------------------------------------------------------------------------------
+ printf("\n2. Make PurchaseRequest Data Start ----------------------------------------\n");
+
+ memset(ReqBuf, 0x00, sizeof(ReqBuf));
+ memset(LicenseUrl, 0x00, sizeof(LicenseUrl));
+ ReqBufLen = sizeof(ReqBuf);
+ LicenseUrlLen = sizeof(LicenseUrl);
+
+ bRet = drm_tizen_generate_purchase_request(testFileName, ReqBuf, &ReqBufLen, LicenseUrl, &LicenseUrlLen);
+ if (bRet == false)
+ {
+ printf(" drm_tizen_generate_purchase_request Error! \n");
+ return 0;
+ }
+
+ printf("drm_tizen_generate_purchase_request - ReqBufLen : %d, License Url : %s \n", ReqBufLen, LicenseUrl);
+ if ((bRet = _write_logfile("Request_1.dat", ReqBuf, ReqBufLen-1)) == false)
+ {
+ printf(" drm_tizen_generate_purchase_request _write_logfile Error! \n");
+ return 0;
+ }
+
+ //break.... HTTP Request & Reaponse Processing...
+ printf ("Enter any key after create Response_1.dat file. --> ");
+ scanf ("%s", tempBuf);
+
+ memset(RespBuf, 0x00, sizeof(RespBuf));
+ RespBufLen = sizeof(RespBuf);
+ if ((bRet = _read_logfile("Response_1.dat", RespBuf, &RespBufLen)) == false)
+ {
+ printf(" drm_tizen_generate_purchase_request _read_logfile Error! \n");
+ return 0;
+ }
+
+ //----------------------------------------------------------------------------------------------------
+ // 3. Make License Request Data
+ //----------------------------------------------------------------------------------------------------
+ printf("\n3. Make License Request Data Start ----------------------------------------\n");
+
+ memset(ReqBuf, 0x00, sizeof(ReqBuf));
+ memset(LicenseUrl, 0x00, sizeof(LicenseUrl));
+ ReqBufLen = sizeof(ReqBuf);
+ LicenseUrlLen = sizeof(LicenseUrl);
+
+ bRet = drm_tizen_generate_license_request(RespBuf, RespBufLen, ReqBuf, &ReqBufLen, LicenseUrl, &LicenseUrlLen);
+ if (bRet != TADC_SUCCESS)
+ {
+ printf(" drm_tizen_generate_license_request Error! \n");
+ return 0;
+ }
+
+ printf("drm_tizen_generate_license_request - ReqBufLen : %d, RO Url : %s \n", ReqBufLen, LicenseUrl);
+ if ((bRet = _write_logfile("Request_2.dat", ReqBuf, ReqBufLen - 1)) == false)
+ {
+ printf(" drm_tizen_generate_license_request _write_logfile Error! \n");
+ return 0;
+ }
+
+ //break.... HTTP Request & Reaponse Processing...
+ printf ("Enter any key after create Response_2.dat file. --> ");
+ scanf ("%s", tempBuf);
+
+ memset(RespBuf, 0x00, sizeof(RespBuf));
+ RespBufLen = sizeof(RespBuf);
+ if ((bRet = _read_logfile("Response_2.dat", RespBuf, &RespBufLen)) == false)
+ {
+ printf(" drm_tizen_generate_license_request _read_logfile Error! \n");
+ return 0;
+ }
+
+ //----------------------------------------------------------------------------------------------------
+ // 4. Decrypt DRM License
+ //----------------------------------------------------------------------------------------------------
+ printf("\n4. Decrypt DRM License Start --------------------------------------------\n");
+
+ bRet = drm_tizen_register_license(RespBuf, RespBufLen);
+ if (bRet != TADC_SUCCESS)
+ {
+ printf(" drm_tizen_register_license Error! \n");
+ return 0;
+ }
+
+ //---------------------------------------------------------------------------------------------------
+ // 5. Decrypt DRM File
+ //----------------------------------------------------------------------------------------------------
+ printf("\n5. Decrypt DRM File Start -----------------------------------------\n");
+
+ sprintf(tempBuf, "%s.dec", testFileName);
+ bRet = drm_tizen_decrypt_package(testFileName, strlen(testFileName), tempBuf, strlen(tempBuf));
+
+ if (bRet != TADC_SUCCESS)
+ {
+ printf(" drm_tizen_decrypt_package Error! \n");
+ return 0;
+ }
+
+ printf("\n --------------Test Tizen Apps DRM APIs --- End ---------------\n");
+
+#endif
+}
diff --git a/test/drm_testutil.cpp b/test/drm_testutil.cpp
new file mode 100644
index 0000000..5fd6b88
--- /dev/null
+++ b/test/drm_testutil.cpp
@@ -0,0 +1,813 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+#include <openssl/buffer.h>
+#include <openssl/bn.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/rsa.h>
+#include <openssl/aes.h>
+#include <openssl/sha.h>
+
+#include <TADC_IF.h>
+#include <drm-tizen-apps.h>
+#include <TADC_Util.h>
+
+#include "drm_testutil.h"
+
+#define _INITIALIZED 0
+#define _UNINITIALIZED -1
+
+static unsigned char g_baSignatureKey[ 32 ] =
+{
+ 0x29, 0x2b, 0xf2, 0x29, 0x1f, 0x8b, 0x47, 0x81, 0x95, 0xa, 0x84, 0xf8, 0x91, 0xda, 0x7, 0xd0,
+ 0x9c, 0xde, 0x32, 0x3e, 0x9e, 0x46, 0x4a, 0xfc, 0xa4, 0xcc, 0x55, 0x6e, 0xf2, 0x81, 0x61, 0xdb
+};
+
+static unsigned char g_baAESKey[ 32 ] =
+{
+ -8, -121, 10, -59, -45, 109, 68, 73, 3, -97, -67, 30, -88, 47, -10,
+ -61, -33, 59, 2, 19, 88, 27, 18, 48, 28, -41, -83, -91, 31, 93, 1, 51
+};
+
+
+int __initialized = _UNINITIALIZED;
+
+void __init_crypto()
+{
+ if(__initialized != _INITIALIZED ) {
+ ERR_load_crypto_strings();
+ OpenSSL_add_all_algorithms();
+ __initialized = _INITIALIZED;
+ }
+}
+
+int __get_random_bytes(char* output, int random_len)
+{
+ FILE *fp;
+ fp = fopen("/dev/urandom", "r");
+ fread(output, 1, random_len, fp);
+ fclose(fp);
+ return DRMTEST_SUCCESS;
+}
+
+int __file_copy(const char* target_path, const char* source_path)
+{
+ int ret = DRMTEST_SUCCESS;
+ FILE *source = NULL;
+ FILE *target = NULL;
+ size_t l1,l2;
+ unsigned char buffer[8192];
+
+ source = fopen(source_path, "r");
+ if(source == NULL) {
+ ret = DRMTEST_ERR_IO;
+ goto error;
+ }
+
+ target = fopen(target_path, "w");
+ if(target == NULL) {
+ ret = DRMTEST_ERR_IO;
+ goto error;
+ }
+
+ while((l1 = fread(buffer, 1, sizeof buffer, source)) > 0) {
+ l2 = fwrite(buffer, 1, l1, target);
+ if(l2 < l1) {
+ if(ferror(target)) {
+ ret = DRMTEST_ERR_IO;
+ goto error;
+ }
+ }
+ }
+
+error:
+ if(source != NULL)
+ fclose(source);
+ if(target != NULL)
+ fclose(target);
+ return ret;
+}
+
+void _base64_encode(const unsigned char* input, int length, char** output)
+{
+ *output = Base64Encode((unsigned char*)input, length);
+}
+
+void _base64_decode(const char* input, unsigned char** output, int* out_len)
+{
+ *output = Base64Decode((char*)input, out_len);
+}
+
+char* _replace_all(char *s, const char *olds, const char *news)
+{
+ char *result=NULL, *sr=NULL;
+ size_t i, count = 0;
+ size_t oldlen = strlen(olds); if (oldlen < 1) return s;
+ size_t newlen = strlen(news);
+
+ if (newlen != oldlen) {
+ for (i = 0; s[i] != '\0';) {
+ if (memcmp(&s[i], olds, oldlen) == 0) count++, i += oldlen;
+ else i++;
+ }
+ } else i = strlen(s);
+
+ result = (char *) malloc(i + 1 + count * (newlen - oldlen));
+ if (result == NULL) return NULL;
+
+ sr = result;
+ while (*s) {
+ if (memcmp(s, olds, oldlen) == 0) {
+ memcpy(sr, news, newlen);
+ sr += newlen;
+ s += oldlen;
+ } else *sr++ = *s++;
+ }
+ *sr = '\0';
+
+ return result;
+}
+
+int _read_text_file(const char* path, char** output)
+{
+ int ret = DRMTEST_SUCCESS;
+ FILE *file = NULL;
+ char *buffer = NULL;
+ unsigned long fileLen;
+
+ //Open file
+ file = fopen(path, "rb");
+ if (file == NULL) {
+ ret = DRMTEST_ERR_IO;
+ goto error;
+ }
+
+ //Get file length
+ fseek(file, 0, SEEK_END);
+ fileLen=ftell(file);
+ fseek(file, 0, SEEK_SET);
+
+ //Allocate memory
+ buffer=(char *)malloc(fileLen+1);
+ if (buffer == NULL) {
+ ret = DRMTEST_ERR_MEMORY;
+ goto error;
+ }
+ memset(buffer, 0, fileLen+1);
+
+ //Read file contents into buffer
+ fread(buffer, fileLen, 1, file);
+
+ *output = buffer;
+error:
+ if(file != NULL)
+ fclose(file);
+ if(ret != DRMTEST_SUCCESS && buffer != NULL)
+ free(buffer);
+
+ return ret;
+}
+
+int _create_dh_key(const char* dh_key_p_hex, const char* dh_key_g_hex, DH** ppkey)
+{
+ int ret = DRMTEST_SUCCESS;
+ DH *pDH = NULL;
+
+ if ((pDH = DH_new()) == NULL) {
+ printf("...FAIL: DH_new() error");
+ ret = DRMTEST_ERR_CRYPTO;
+ goto error;
+ }
+
+ BN_hex2bn(&(pDH->p), dh_key_p_hex);
+ BN_hex2bn(&(pDH->g), dh_key_g_hex);
+
+ /* Set a to run with normal modexp and b to use constant time */
+ pDH->flags &= ~DH_FLAG_NO_EXP_CONSTTIME;
+
+ // Generate DH Key
+ if (!DH_generate_key(pDH)) {
+ printf("...FAIL: DH_generate_key");
+ ret = DRMTEST_ERR_CRYPTO;
+ goto error;
+ }
+
+ *ppkey = pDH;
+error:
+ if(ret != DRMTEST_SUCCESS && pDH != NULL)
+ DH_free(pDH);
+
+ return ret;
+}
+
+int _free_dh_key(DH* pkey)
+{
+ if(pkey != NULL)
+ DH_free(pkey);
+ return DRMTEST_SUCCESS;
+}
+
+
+int _get_dh_hex_pubkey(const DH* pkey, char** dh_pubkey)
+{
+ *dh_pubkey = BN_bn2hex(pkey->pub_key);
+ return DRMTEST_SUCCESS;
+}
+
+int _get_dh_shared_secret_key(const char* dh_hex_pubkey, DH *pkey,
+ unsigned char** dh_shared_secret_key, int *dh_sec_key_len)
+{
+ int ret = DRMTEST_SUCCESS;
+
+ BIGNUM *pPubKey = NULL;
+ unsigned char *secret_key_buff = NULL;
+ unsigned char tmp_buff[DH_size(pkey)] = {0,};
+
+
+ BN_hex2bn(&pPubKey, dh_hex_pubkey);
+
+ if(DH_compute_key(tmp_buff, pPubKey, pkey) < 0) {
+ ret = DRMTEST_ERR_CRYPTO;
+ goto error;
+ }
+
+ secret_key_buff = (unsigned char *) malloc(DH_size(pkey)/2);
+ if(secret_key_buff == NULL) {
+ ret = DRMTEST_ERR_CRYPTO;
+ goto error;
+ }
+ memset(secret_key_buff, 0, DH_size(pkey)/2);
+
+printf("APP_DRM TEST: shared secret : ");
+ for(int i=0; i<(DH_size(pkey)/2); i++) {
+ secret_key_buff[i] = tmp_buff[i * 2] ^ tmp_buff[(i * 2) + 1];
+ printf("%02x", secret_key_buff[i]);
+ }
+printf("\n");
+
+ *dh_shared_secret_key = secret_key_buff;
+ *dh_sec_key_len = DH_size(pkey)/2;
+error:
+ if(pPubKey != NULL)
+ BN_free(pPubKey);
+ if(ret != DRMTEST_SUCCESS && secret_key_buff != NULL)
+ free(secret_key_buff);
+
+ return ret;
+}
+
+
+int _create_right_object_without_signature(const char* ro_template_path, const char* cid, const char* duid,
+ char** ro_buff)
+{
+ int ret = DRMTEST_SUCCESS;
+ char *file_buff = NULL;
+ char *cid_filled = NULL;
+ char *duid_filled = NULL;
+
+ ret = _read_text_file(ro_template_path, &file_buff);
+ if(ret != DRMTEST_SUCCESS) {
+ goto error;
+ }
+
+ cid_filled = _replace_all(file_buff, STR_PLACE_HOLDER_CID, cid);
+ duid_filled = _replace_all(cid_filled, STR_PLACE_HOLDER_DUID, duid);
+
+ *ro_buff = duid_filled;
+error:
+ if(file_buff != NULL)
+ free(file_buff);
+ if(cid_filled != NULL)
+ free(cid_filled);
+ if(ret != DRMTEST_SUCCESS && duid_filled != NULL)
+ free(duid_filled);
+
+ return ret;
+}
+
+int _create_ro_signature(const char* ro_buff, const char* signer_prikey_path, char** signature)
+{
+ int ret = DRMTEST_SUCCESS;
+
+ EVP_PKEY* pkey = NULL;
+ RSA* prsa = NULL;
+ const char* END_STR = "</CertificateChain>";
+ const char* tmp_end_hash_input = NULL;
+ int hash_input_size = 0;
+ unsigned char hash_value[20];
+ unsigned char sig_value[MAX_CERT_SIZE]; // enough buffer
+ unsigned int sig_len = 0;
+ char* b64_sig_value = NULL;
+
+ FILE *file = NULL;
+
+ // get private key
+ file = fopen(signer_prikey_path, "r");
+ if(file == NULL) {
+ ret = DRMTEST_ERR_IO;
+ goto error;
+ }
+
+ pkey = PEM_read_PrivateKey(file, &pkey, NULL, NULL);
+ if(pkey == NULL) {
+ ret = DRMTEST_ERR_IO;
+ goto error;
+ }
+
+ prsa = EVP_PKEY_get1_RSA(pkey);
+ if(prsa == NULL) {
+ ret = DRMTEST_ERR_CRYPTO;
+ goto error;
+ }
+
+ // get hash input size
+ tmp_end_hash_input = strstr(ro_buff, END_STR);
+ hash_input_size = (tmp_end_hash_input - ro_buff) + strlen(END_STR);
+
+ // get hash value
+ SHA_CTX alginfo;
+ SHA1_Init(&alginfo);
+ SHA1_Update(&alginfo, ro_buff, hash_input_size);
+ SHA1_Final(hash_value, &alginfo);
+
+ // get signature value
+ if( 1 != RSA_sign(NID_sha1, hash_value, 20, sig_value, &sig_len, prsa) ) {
+ ret = DRMTEST_ERR_CRYPTO;
+ goto error;
+ }
+
+ // convert to base64 string
+ _base64_encode(sig_value, (int) sig_len, &b64_sig_value);
+
+ *signature = b64_sig_value;
+error:
+ if(file != NULL)
+ fclose(file);
+ if(pkey != NULL)
+ EVP_PKEY_free(pkey);
+ if(ret != DRMTEST_SUCCESS && b64_sig_value != NULL)
+ free(b64_sig_value);
+
+ return ret;
+}
+
+int _add_signature_to_ro(const char* ro_buff, const char* signature, char** ro_with_signature)
+{
+ int ret = DRMTEST_SUCCESS;
+ char *buff = NULL;
+ buff = _replace_all((char*)ro_buff, STR_PLACE_HOLDER_SIGNATURE, signature);
+ *ro_with_signature = buff;
+ return ret;
+}
+
+int _encrypt_ro_with_dh_sec_key(const char* ro_with_signature,
+ const unsigned char* dh_secret_key, const int dh_sec_key_len,
+ char **encrypted_ro)
+{
+ int ret = DRMTEST_SUCCESS;
+ TADC_U8 key[16] = {0, };
+ TADC_U8 iv[16] = {0, };
+ int encrypted_len = 0;
+ unsigned char encrypted_buff[MAX_CERT_SIZE] = {0, };;
+
+ (void) dh_sec_key_len; // to prevent unused varialbe error
+
+ TADC_IF_MemCpy(key, dh_secret_key, 16);
+ TADC_IF_MemCpy(iv, (dh_secret_key+16), 16);
+ ret = TADC_IF_AES_CTR(16, key, 16, iv, strlen(ro_with_signature), (unsigned char*)ro_with_signature,
+ &encrypted_len, (unsigned char*)encrypted_buff);
+ if(ret != 0) {
+ ret = DRMTEST_ERR_CRYPTO;
+ goto error;
+ }
+
+ _base64_encode(encrypted_buff, encrypted_len, encrypted_ro);
+
+error:
+ return ret;
+}
+
+int _create_response_data_in_ro_response(const char* reqid, const char* encrypted_ro, const char* dh_pubkey,
+ char **response_data)
+{
+ int ret = DRMTEST_SUCCESS;
+ char tmp_buff[MAX_CERT_SIZE] = {0,};
+ unsigned char hashed_reqid[20]={0,};
+ char hex_hashed_reqid[256] = {0, };
+ unsigned char hash_value[20]={0,};
+ int hmac_len = 0;
+ unsigned char hmac[1024*10] = {0,};
+ char* hmac_base64 = NULL;
+ char* resp_data = NULL;
+
+ // get hashed req_id
+ SHA_CTX alginfoForReqId;
+ SHA1_Init(&alginfoForReqId);
+ SHA1_Update(&alginfoForReqId, reqid, strlen(reqid));
+ SHA1_Final(hashed_reqid, &alginfoForReqId);
+
+ for(int i=0; i<sizeof(hashed_reqid); i++) {
+ sprintf(hex_hashed_reqid + i*2, "%02x", hashed_reqid[i]);
+ }
+ sprintf(tmp_buff, "reqid=%s;B=%s;license=%s", hex_hashed_reqid, dh_pubkey, encrypted_ro);
+
+ // get hash value
+ SHA_CTX alginfo;
+ SHA1_Init(&alginfo);
+ SHA1_Update(&alginfo, tmp_buff, strlen(tmp_buff));
+ SHA1_Final(hash_value, &alginfo);
+
+ // encrypt hash value
+ TADC_U8 key[16] = {0, };
+ TADC_U8 iv[16] = {0, };
+
+ TADC_IF_MemCpy(key, g_baAESKey, 16);
+ TADC_IF_MemCpy(iv, (g_baAESKey+16), 16);
+ ret = TADC_IF_AES_CTR(16, key, 16, iv, 20, hash_value, &hmac_len, hmac);
+ if(ret != 0) {
+ ret = DRMTEST_ERR_CRYPTO;
+ goto error;
+ }
+
+ // base64 encode
+ _base64_encode(hmac, 20, &hmac_base64);
+
+ // add hmac
+ strncat(tmp_buff, ";hmac=", strlen(";hmac="));
+ strncat(tmp_buff, hmac_base64, strlen(hmac_base64));
+
+ // make return value
+ resp_data = (char*) malloc(strlen(tmp_buff)+1);
+ if(resp_data == NULL) {
+ ret = DRMTEST_ERR_MEMORY;
+ goto error;
+ }
+ memset(resp_data, 0, strlen(tmp_buff)+1);
+ strncpy(resp_data, tmp_buff, strlen(tmp_buff));
+
+ *response_data = resp_data;
+
+error:
+ if(hmac_base64 != NULL)
+ free(hmac_base64);
+ if(ret != DRMTEST_SUCCESS && resp_data != NULL)
+ free(resp_data);
+ return ret;
+}
+
+int _create_time_stamp(const unsigned char* dh_secret_key, char** time_stamp)
+{
+ int ret = DRMTEST_SUCCESS;
+
+ char tmp_time_buff[128] = {0,};
+ unsigned char enc_time_buff[512] = {0,};
+ char *time_base64 = NULL;
+ int enc_time_buff_len = 0;
+ time_t now = time(NULL);
+ const struct tm* gt = gmtime(&now);
+
+ sprintf(tmp_time_buff, "%d-%d-%dT%d:%d:00:Z",
+ gt->tm_year+1900, gt->tm_mon+1, gt->tm_mday,
+ gt->tm_hour+1, gt->tm_min+1);
+
+ // encrypt time_stamp
+ TADC_U8 key[16] = {0, };
+ TADC_U8 iv[16] = {0, };
+
+ TADC_IF_MemCpy(key, dh_secret_key, 16);
+ TADC_IF_MemCpy(iv, (dh_secret_key+16), 16);
+ ret = TADC_IF_AES_CTR(16, key, 16, iv, strlen(tmp_time_buff), (unsigned char*)tmp_time_buff,
+ &enc_time_buff_len, enc_time_buff);
+ if(ret != 0) {
+ ret = DRMTEST_ERR_CRYPTO;
+ goto error;
+ }
+
+ // convert to base64
+ _base64_encode(enc_time_buff, enc_time_buff_len, &time_base64);
+
+ *time_stamp = time_base64;
+error:
+ if(ret != DRMTEST_SUCCESS && time_base64 != NULL)
+ free(time_base64);
+ return ret;
+
+}
+
+static int req_id_seq = 0;
+
+int generate_purchase_response(char** purchase_response_buff, char** req_id)
+{
+ int ret = DRMTEST_SUCCESS;
+ char resp_buff[1024*5] = {0, };
+ char *resp = NULL;
+ char *rid = NULL;
+ char random[64] = {0, };
+
+ const char *format1 = "<?xml version=\"1.0\">\n";
+ const char *format2 = "<response result=\"0\" message=\"\">\n";
+ const char *format3 = " <DRMType>%d</DRMType>\n";
+ const char *format4 = " <riurl>%s</riurl>\n";
+ const char *format5 = " <reqid>%s</reqid>\n";
+ const char *format6 = "</response>";
+
+ resp = (char*) malloc(sizeof(resp_buff));
+ if(resp == NULL) {
+ ret = DRMTEST_ERR_MEMORY;
+ goto error;
+ }
+ memset(resp, 0, sizeof(resp_buff));
+
+ __get_random_bytes(random, sizeof(random));
+ rid = (char*) malloc(1024);
+ if(rid == NULL) {
+ ret = DRMTEST_ERR_MEMORY;
+ goto error;
+ }
+ memset(rid, 0, 1024);
+
+ for(int i=0; i<sizeof(random); i++) {
+ sprintf(rid + i*2, "%02x", random[i]);
+ }
+
+ strncat(resp_buff, format1, strlen(format1));
+ strncat(resp_buff, format2, strlen(format2));
+ strncat(resp_buff, format3, strlen(format3));
+ strncat(resp_buff, format4, strlen(format4));
+ strncat(resp_buff, format5, strlen(format5));
+ strncat(resp_buff, format6, strlen(format6));
+
+ sprintf(resp, resp_buff, 1, RIURL, rid);
+
+ *purchase_response_buff = resp;
+ *req_id = rid;
+
+error:
+ if(ret != DRMTEST_SUCCESS && resp != NULL)
+ free(resp);
+ if(ret != DRMTEST_SUCCESS && rid != NULL)
+ free(rid);
+
+ return ret;
+}
+
+int generate_right_object_request(const char* license_response_buff,
+ char** ro_request_buff)
+{
+ int ret = DRMTEST_SUCCESS;
+ unsigned int req_buff_len = 1024*5;
+ char url_buff[1024] = {0, };
+ unsigned int url_buff_len = sizeof(url_buff);
+ char *req_buff = NULL;
+
+ req_buff = (char *)malloc(1024*5);
+ if(req_buff == NULL) {
+ ret = DRMTEST_ERR_MEMORY;
+ goto error;
+ }
+ memset(req_buff, 0, req_buff_len);
+
+ ret = drm_tizen_generate_license_request(license_response_buff, strlen(license_response_buff),
+ req_buff, &req_buff_len, url_buff, &url_buff_len);
+ if(ret != 1) {
+ ret = DRMTEST_ERR_TIZDRM;
+ goto error;
+ }
+
+error:
+ if(ret != DRMTEST_SUCCESS && req_buff != NULL)
+ free(req_buff);
+ return ret;
+}
+
+
+int get_dh_key_from_ro_request(const char* ro_request_buff,
+ char** dh_key_p, char** dh_key_g, char** dh_key_a)
+{
+ int ret = DRMTEST_SUCCESS;
+
+ const char* PFX_P = "p=";
+ const char* PFX_G = ";g=";
+ const char* PFX_A = ";A=";
+ const char* PFX_HMAC = ";hmac=";
+
+ const char * idx_p = strstr(ro_request_buff, PFX_P);
+ const char * idx_g = strstr(ro_request_buff, PFX_G);
+ const char * idx_a = strstr(ro_request_buff, PFX_A);
+ const char * idx_hmac = strstr(ro_request_buff, PFX_HMAC);
+
+ int len_p = idx_g - idx_p - strlen(PFX_P);
+ int len_g = idx_a - idx_g - strlen(PFX_G);
+ int len_a = idx_hmac - idx_a - strlen(PFX_A);
+
+ char* buff_p = NULL;
+ char* buff_g = NULL;
+ char* buff_a = NULL;
+
+ buff_p = (char *)malloc(len_p + 1);
+ if(buff_p == NULL) {
+ ret = DRMTEST_ERR_MEMORY;
+ goto error;
+ }
+ memset(buff_p, 0, len_p + 1);
+ strncpy(buff_p, idx_p + strlen(PFX_P), len_p);
+ *dh_key_p = buff_p;
+
+ buff_g = (char *)malloc(len_g + 1);
+ if(buff_g == NULL) {
+ ret = DRMTEST_ERR_MEMORY;
+ goto error;
+ }
+ memset(buff_g, 0, len_g + 1);
+ strncpy(buff_g, idx_g + strlen(PFX_G), len_g);
+ *dh_key_g = buff_g;
+
+ buff_a = (char *)malloc(len_a + 1);
+ if(buff_a == NULL) {
+ ret = DRMTEST_ERR_MEMORY;
+ goto error;
+ }
+ memset(buff_a, 0, len_a + 1);
+ strncpy(buff_a, idx_a + strlen(PFX_A), len_a);
+ *dh_key_a = buff_a;
+
+error:
+ if(ret != DRMTEST_SUCCESS && buff_p != NULL)
+ free(buff_p);
+ if(ret != DRMTEST_SUCCESS && buff_g != NULL)
+ free(buff_g);
+ if(ret != DRMTEST_SUCCESS && buff_a != NULL)
+ free(buff_a);
+
+ return ret;
+}
+
+int generate_right_object_response(const char* dh_key_p, const char* dh_key_g, const char* dh_key_a,
+ const char* req_id, const char* cid, const char* ro_template_path,
+ const char* duid, char** ro_response_buff)
+{
+ int ret = DRMTEST_SUCCESS;
+
+ DH* pkey = NULL;
+ char* dh_pubkey = NULL;
+ unsigned char* dh_shared_secret_key = NULL;
+ int dh_sec_key_len = 0;
+ char* ro_buff = NULL;
+ char* ro_signature = NULL;
+ char* ro_with_signature = NULL;
+ char* encrypted_ro = NULL;
+ char* response_data = NULL;
+ char* time_stamp = NULL;
+ char* ro_resp_buff = NULL;
+ int ro_resp_buff_len = 0;
+
+ const char *format = "<?xml version=\"1.0\">\n"
+ "<response result=\"0\" message=\"\">\n"
+ " <responsedata>%s</responsedata>\n"
+ " <timeStamp>%s</timeStamp>\n"
+ "</response>";
+
+ ret = _create_dh_key(dh_key_p, dh_key_g, &pkey);
+ if(ret != DRMTEST_SUCCESS){
+ goto error;
+ }
+
+ ret = _get_dh_hex_pubkey(pkey, &dh_pubkey);
+ if(ret != DRMTEST_SUCCESS){
+ goto error;
+ }
+
+ ret = _get_dh_shared_secret_key(dh_key_a, pkey, &dh_shared_secret_key, &dh_sec_key_len);
+ if(ret != DRMTEST_SUCCESS){
+ goto error;
+ }
+
+ ret = _create_right_object_without_signature(ro_template_path, cid, duid, &ro_buff);
+ if(ret != DRMTEST_SUCCESS){
+ goto error;
+ }
+
+ ret = _create_ro_signature(ro_buff, RO_ISSUER_SIGNER_KEY_FILE, &ro_signature);
+ if(ret != DRMTEST_SUCCESS){
+ goto error;
+ }
+
+ ret = _add_signature_to_ro(ro_buff, ro_signature, &ro_with_signature);
+ if(ret != DRMTEST_SUCCESS){
+ goto error;
+ }
+ //printf("...right object:\n%s\n", ro_with_signature);
+
+ ret = _encrypt_ro_with_dh_sec_key(ro_with_signature, dh_shared_secret_key, dh_sec_key_len,
+ &encrypted_ro);
+ if(ret != DRMTEST_SUCCESS){
+ goto error;
+ }
+
+ ret = _create_response_data_in_ro_response(req_id, encrypted_ro, dh_pubkey, &response_data);
+ if(ret != DRMTEST_SUCCESS){
+ goto error;
+ }
+
+ ret = _create_time_stamp( dh_shared_secret_key, &time_stamp);
+ if(ret != DRMTEST_SUCCESS){
+ goto error;
+ }
+
+ ro_resp_buff_len = strlen(format) + strlen(response_data) + strlen(time_stamp) + 1;
+ ro_resp_buff = (char *) malloc(ro_resp_buff_len);
+ if(ro_resp_buff == NULL) {
+ ret = DRMTEST_ERR_MEMORY;
+ goto error;
+ }
+ memset(ro_resp_buff, 0, ro_resp_buff_len);
+ sprintf(ro_resp_buff, format, response_data, time_stamp);
+
+ *ro_response_buff = ro_resp_buff;
+
+error:
+ if(pkey != NULL)
+ _free_dh_key(pkey);
+ if(dh_pubkey != NULL)
+ free(dh_pubkey);
+ if(dh_shared_secret_key != NULL)
+ free(dh_shared_secret_key);
+ if(ro_buff != NULL)
+ free(ro_buff);
+ if(ro_signature != NULL)
+ free(ro_signature);
+ if(ro_with_signature != NULL)
+ free(ro_with_signature);
+ if(encrypted_ro != NULL)
+ free(encrypted_ro);
+ if(response_data != NULL)
+ free(response_data);
+ if(time_stamp != NULL)
+ free(time_stamp);
+ if(ret != DRMTEST_SUCCESS && ro_resp_buff != NULL)
+ free(ro_resp_buff);
+
+ return ret;
+}
+
+
+int is_identical_files(const char* file1, const char* file2, int* identical)
+{
+ int ret = DRMTEST_SUCCESS;
+
+ FILE *fp1 = NULL, *fp2 = NULL;
+ int ch1, ch2;
+
+ fp1 = fopen(file1, "r");
+ if(fp1 == NULL) {
+ ret = DRMTEST_ERR_IO;
+ goto error;
+ }
+
+ fp2 = fopen(file2, "r");
+ if(fp2 == NULL) {
+ ret = DRMTEST_ERR_IO;
+ goto error;
+ }
+
+ ch1 = getc(fp1);
+ ch2 = getc(fp2);
+ while ((ch1 != EOF) && (ch2 != EOF) && (ch1 == ch2)) {
+ ch1 = getc(fp1);
+ ch2 = getc(fp2);
+ }
+ if(ch1 == ch2)
+ *identical = DRMTEST_IDENTICAL;
+ else
+ *identical = DRMTEST_NOTIDENTICAL;
+
+error:
+ if(fp1 != NULL)
+ fclose(fp1);
+ if(fp2 != NULL)
+ fclose(fp2);
+ return ret;
+}
+
diff --git a/test/drm_testutil.h b/test/drm_testutil.h
new file mode 100644
index 0000000..2eb8739
--- /dev/null
+++ b/test/drm_testutil.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * 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 <openssl/dh.h>
+#include <tzplatform_config.h>
+
+
+#define RIURL "http://appdrm.test.com/"
+
+#define RO_ISSUER_SIGNER_KEY_FILE tzplatform_mkpath(TZ_SYS_DATA, "drm_test/Key/ro_test_signer.key")
+
+#define STR_PLACE_HOLDER_CID "PLACE_HOLDER_FOR_CID"
+#define STR_PLACE_HOLDER_DUID "PLACE_HOLDER_FOR_DUID"
+#define STR_PLACE_HOLDER_SIGNATURE "PLACE_HOLDER_FOR_SIGNATURE"
+
+#define MAX_CERT_SIZE (1024*128)
+
+#define DRMTEST_SUCCESS ( 0)
+#define DRMTEST_ERR_CRYPTO (-1)
+#define DRMTEST_ERR_IO (-2)
+#define DRMTEST_ERR_MEMORY (-3)
+#define DRMTEST_ERR_TIZDRM (-4)
+#define DRMTEST_ERR_PARAM (-5)
+
+#define DRMTEST_IDENTICAL ( 0)
+#define DRMTEST_NOTIDENTICAL (-1)
+
+#define DRMTEST_TEST_ROOT_CERT (1)
+#define DRMTEST_REAL_ROOT_CERT (2)
+
+#define EVP_SUCCESS 1 // DO NOTCHANGE THIS VALUE
+
+int generate_purchase_response(char** purchase_response_buff, char** req_id);
+
+int generate_right_object_request(const char* license_response_buff,
+ char** ro_request_buff);
+
+int get_dh_key_from_ro_request(const char* ro_request_buff,
+ char** dh_key_p, char** dh_key_g, char** dh_key_a);
+
+int generate_right_object_response(const char* dh_key_p, const char* dh_key_g, const char* dh_key_a,
+ const char* req_id, const char* cid, const char* ro_template_path,
+ const char* duid, char** ro_response_buff);
+int is_identical_files(const char* file1, const char* file2, int* identical);
+
+int switch_root_cert(int target_cert_type);
+
+
+void _base64_encode(const unsigned char* input, int len, char** output);
+void _base64_decode(const char* input, unsigned char** output, int* out_len);
+char* _replace_all(char *s, const char *olds, const char *news);
+int _read_text_file(const char* path, char** output);
+
+int _create_dh_key(const char* dh_key_p_hex, const char* dh_key_g_hex, DH** ppkey);
+int _free_dh_key(DH* pkey);
+int _get_dh_hex_pubkey(const DH* pkey, char** dh_pubkey);
+int _get_dh_shared_secret_key(const char* dh_hex_pubkey, DH *pkey,
+ unsigned char** dh_shared_secret_key, int *dh_sec_key_len);
+
+int _create_right_object_without_signature(const char* ro_template_path, const char* cid, const char* duid,
+ char** ro_buff);
+int _create_ro_signature(const char* ro_buff, const char* signer_prikey_path, char** signature);
+int _add_signature_to_ro(const char* ro_buff, const char* signature, char** ro_with_signature);
+int _encrypt_ro_with_dh_sec_key(const char* ro_with_signature,
+ const unsigned char* dh_secret_key, const int dh_sec_key_len,
+ char **encrypted_ro);
+
+int _create_response_data_in_ro_response(const char* reqid, const char* encrypted_ro, const char* dh_pubkey,
+ char **response_data);
+
+int _create_time_stamp(const unsigned char* dh_secret_key, char** time_stamp);
+
+
diff --git a/test/sample_contents/DB/.dtapps.db b/test/sample_contents/DB/.dtapps.db
new file mode 100644
index 0000000..45e839c
--- /dev/null
+++ b/test/sample_contents/DB/.dtapps.db
Binary files differ
diff --git a/test/sample_contents/DB/.dtapps.db-journal b/test/sample_contents/DB/.dtapps.db-journal
new file mode 100644
index 0000000..39b6084
--- /dev/null
+++ b/test/sample_contents/DB/.dtapps.db-journal
Binary files differ
diff --git a/test/sample_contents/DCF/38EIfBurLJ.tpk b/test/sample_contents/DCF/38EIfBurLJ.tpk
new file mode 100644
index 0000000..8f62501
--- /dev/null
+++ b/test/sample_contents/DCF/38EIfBurLJ.tpk
Binary files differ
diff --git a/test/sample_contents/DCF/8SPXfqc6iL.tpk b/test/sample_contents/DCF/8SPXfqc6iL.tpk
new file mode 100644
index 0000000..524c1f3
--- /dev/null
+++ b/test/sample_contents/DCF/8SPXfqc6iL.tpk
Binary files differ
diff --git a/test/sample_contents/DCF/FightGuiIF.tpk b/test/sample_contents/DCF/FightGuiIF.tpk
new file mode 100644
index 0000000..534c9c7
--- /dev/null
+++ b/test/sample_contents/DCF/FightGuiIF.tpk
Binary files differ
diff --git a/test/sample_contents/DCF/X5YVR2zmQZ.tpk b/test/sample_contents/DCF/X5YVR2zmQZ.tpk
new file mode 100644
index 0000000..b224296
--- /dev/null
+++ b/test/sample_contents/DCF/X5YVR2zmQZ.tpk
Binary files differ
diff --git a/test/sample_contents/DCF/ZdAXXZx2HZ.tpk b/test/sample_contents/DCF/ZdAXXZx2HZ.tpk
new file mode 100644
index 0000000..8153f53
--- /dev/null
+++ b/test/sample_contents/DCF/ZdAXXZx2HZ.tpk
Binary files differ
diff --git a/test/sample_contents/DCF/basiccoreuiapp_drm.tpk b/test/sample_contents/DCF/basiccoreuiapp_drm.tpk
new file mode 100644
index 0000000..b1434e7
--- /dev/null
+++ b/test/sample_contents/DCF/basiccoreuiapp_drm.tpk
Binary files differ
diff --git a/test/sample_contents/DCF/lXs4HhBlYZ.tpk b/test/sample_contents/DCF/lXs4HhBlYZ.tpk
new file mode 100644
index 0000000..bf518fb
--- /dev/null
+++ b/test/sample_contents/DCF/lXs4HhBlYZ.tpk
Binary files differ
diff --git a/test/sample_contents/DecryptedApp/38EIfBurLJ_dec.tpk b/test/sample_contents/DecryptedApp/38EIfBurLJ_dec.tpk
new file mode 100644
index 0000000..248bb61
--- /dev/null
+++ b/test/sample_contents/DecryptedApp/38EIfBurLJ_dec.tpk
Binary files differ
diff --git a/test/sample_contents/DecryptedApp/8SPXfqc6iL_dec.tpk b/test/sample_contents/DecryptedApp/8SPXfqc6iL_dec.tpk
new file mode 100644
index 0000000..9cda458
--- /dev/null
+++ b/test/sample_contents/DecryptedApp/8SPXfqc6iL_dec.tpk
Binary files differ
diff --git a/test/sample_contents/DecryptedApp/FightGuiIF_dec.tpk b/test/sample_contents/DecryptedApp/FightGuiIF_dec.tpk
new file mode 100644
index 0000000..59efd2b
--- /dev/null
+++ b/test/sample_contents/DecryptedApp/FightGuiIF_dec.tpk
Binary files differ
diff --git a/test/sample_contents/DecryptedApp/basiccoreuiapp_signed.tpk b/test/sample_contents/DecryptedApp/basiccoreuiapp_signed.tpk
new file mode 100644
index 0000000..0ec2114
--- /dev/null
+++ b/test/sample_contents/DecryptedApp/basiccoreuiapp_signed.tpk
Binary files differ
diff --git a/test/sample_contents/DecryptedTPK/X5YVR2zmQZ.tpk.dec b/test/sample_contents/DecryptedTPK/X5YVR2zmQZ.tpk.dec
new file mode 100644
index 0000000..49354c1
--- /dev/null
+++ b/test/sample_contents/DecryptedTPK/X5YVR2zmQZ.tpk.dec
Binary files differ
diff --git a/test/sample_contents/DecryptedTPK/ZdAXXZx2HZ.tpk.dec b/test/sample_contents/DecryptedTPK/ZdAXXZx2HZ.tpk.dec
new file mode 100644
index 0000000..18059da
--- /dev/null
+++ b/test/sample_contents/DecryptedTPK/ZdAXXZx2HZ.tpk.dec
Binary files differ
diff --git a/test/sample_contents/DecryptedTPK/lXs4HhBlYZ.tpk.dec b/test/sample_contents/DecryptedTPK/lXs4HhBlYZ.tpk.dec
new file mode 100644
index 0000000..dee4f1d
--- /dev/null
+++ b/test/sample_contents/DecryptedTPK/lXs4HhBlYZ.tpk.dec
Binary files differ
diff --git a/test/sample_contents/KEYS/ro_test_root_ca.key b/test/sample_contents/KEYS/ro_test_root_ca.key
new file mode 100644
index 0000000..22c2716
--- /dev/null
+++ b/test/sample_contents/KEYS/ro_test_root_ca.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAwRnSr0Rm/f6AgGNGzOtg3YYtYdJC5Pk4ISc66xTC7ZB6c8qd
+RjOn9YMO5xMjABkQCPhyS6vCefgkrIP2lyPCyjZzEIftLRgM6tiXyo1wDUgKzgRs
+YADdEA122Q3hlJonmx2RMDTQGvS4gSYZcO+1qLCkajd53v5MEibIwOAR3Tm5QzAZ
+VatqrknlHMGcPsGNhA7sIATdiDeiUNB0AJnNaq7AuWi/IIBgIdLzrGpcMPu7JTLa
+/MtH3Vi3y7l168pu4LrZsJNFFExsTBvnrRq0entiaIN60oJVG5+6PX96mgECYtZ2
+ol1UjMyl0NPFoBZv3MzdFHNq707aYB8LcYsNbQIDAQABAoIBAQC8C3alYZpebJIc
+9RDEi893yqu1IDoumxfzCS4SMdSl3lWxHzXLYJCGwMspcfRaqw13fuJnGGu5tVGZ
+gqUHiDawDxg8l/H7QPmLVcNz6AqflHGZMKuNTin48PO06hSsTvaU0tVJuZSTO4/V
+jRGnbnhcPzDNkxqmcsQHxSco1Mvwvws/cagGc2v+Ht1GgrXrqRLOx79XOqphU7qF
+yWkto34ggZuYrf6vRjui+sExegDyYLyOaYzN/63RyEOl5LpPQpQ9xzZhCBDZRnWc
+624oMbkPLniJLF2YNImbagfF4icmGysjtn4St5ssnU3ytoh0pA/oIlzn7fd4W7cL
+OtSIiAQNAoGBAPewgK8BuJmEnwjnF7sHyv7dfKi8vagcSBcbegtQ3coIJamB5nfA
+1XTh0KRd1yzRcQ/xUPgJgwk0poXTDuHMSW4Yz0QLWWiKg4Uega9JRvOEQAJ4SC2A
+2SoLgYbFSIo/wAV8rSvFujQkLRrXE1UGmuUAiu1zLmWNVYZII1soIJ6bAoGBAMeU
+cEG++VuJHW1SbZfphcWb5S/KAWUdc6dko1oug6sndZd8hw8H8lbMSKZbg6wGOaJm
+xbPssqauGEdsN0ucwCtyZCc0G50E6no2PAEkE8zEahtJrqZKH4o/10UZZ94avzlW
+Kf3B4z8RznW4Vr5ZKiUCv4Xs1mTeVDmgvPdVAICXAoGAMl4rHOt9rYJBkN7lfXwN
+NJy3r9yJuLjflAtbWxe7skzL09d9lVaaUaVl9za5/fwtQK+y5m2Qvvt87XPI7/PJ
+7uCOrWidatvX+OcGOi3thrGbDqWFD/PGtX0Xft95a9ug4bzDvkX8IoREw9N+s+ie
+8PiWR8kHY1FFVgQvZGcZkwcCgYBhFlO5l/Zj0gLPsJ6BnOcnZxwJsGIXV0lwr+NL
+Nn903kA1Di4BYONB2CSrUK9wGqMk3ovkaAvMS7qh3AHWNY3CVOZlr9KTAtYx13o/
+L9a18QKQ/boJSNuo/D9zbNV7VVWaxdCtkglDIB1oZOFFvchjsr+Kndj5vrIISqpC
+Q0Z4RwKBgHs2deprc7P/+ZM5Yv3ldmsLVtdScaLQQqyU2oKD1WxOdBbEpa8c7qQZ
+o8SwEk0uI464wzkZpr2+tRIJgWezy8CBB97g8uMTOqUGW2ROla3nET1FxvdgxO5q
+vryPn2cU1kVN7yCfwkUAoV6BPQjwIVViaOjSdA4p5XAIhnAIs20A
+-----END RSA PRIVATE KEY-----
diff --git a/test/sample_contents/KEYS/ro_test_root_ca.pem b/test/sample_contents/KEYS/ro_test_root_ca.pem
new file mode 100644
index 0000000..aaa3383
--- /dev/null
+++ b/test/sample_contents/KEYS/ro_test_root_ca.pem
@@ -0,0 +1,80 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=KR, ST=Seoul, O=Samsung, OU=Tizen Test, CN=DRM Test Root CA/emailAddress=tt@gmail.com
+ Validity
+ Not Before: May 13 02:40:08 2015 GMT
+ Not After : May 10 02:40:08 2025 GMT
+ Subject: C=KR, ST=Seoul, O=Samsung, OU=Tizen Test, CN=DRM Test Root CA/emailAddress=tt@gmail.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c1:19:d2:af:44:66:fd:fe:80:80:63:46:cc:eb:
+ 60:dd:86:2d:61:d2:42:e4:f9:38:21:27:3a:eb:14:
+ c2:ed:90:7a:73:ca:9d:46:33:a7:f5:83:0e:e7:13:
+ 23:00:19:10:08:f8:72:4b:ab:c2:79:f8:24:ac:83:
+ f6:97:23:c2:ca:36:73:10:87:ed:2d:18:0c:ea:d8:
+ 97:ca:8d:70:0d:48:0a:ce:04:6c:60:00:dd:10:0d:
+ 76:d9:0d:e1:94:9a:27:9b:1d:91:30:34:d0:1a:f4:
+ b8:81:26:19:70:ef:b5:a8:b0:a4:6a:37:79:de:fe:
+ 4c:12:26:c8:c0:e0:11:dd:39:b9:43:30:19:55:ab:
+ 6a:ae:49:e5:1c:c1:9c:3e:c1:8d:84:0e:ec:20:04:
+ dd:88:37:a2:50:d0:74:00:99:cd:6a:ae:c0:b9:68:
+ bf:20:80:60:21:d2:f3:ac:6a:5c:30:fb:bb:25:32:
+ da:fc:cb:47:dd:58:b7:cb:b9:75:eb:ca:6e:e0:ba:
+ d9:b0:93:45:14:4c:6c:4c:1b:e7:ad:1a:b4:7a:7b:
+ 62:68:83:7a:d2:82:55:1b:9f:ba:3d:7f:7a:9a:01:
+ 02:62:d6:76:a2:5d:54:8c:cc:a5:d0:d3:c5:a0:16:
+ 6f:dc:cc:dd:14:73:6a:ef:4e:da:60:1f:0b:71:8b:
+ 0d:6d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 33:56:CF:8A:7F:70:9C:63:2B:05:D6:BD:3F:78:1B:77:3C:89:73:46
+ X509v3 Authority Key Identifier:
+ keyid:33:56:CF:8A:7F:70:9C:63:2B:05:D6:BD:3F:78:1B:77:3C:89:73:46
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: sha256WithRSAEncryption
+ 05:ae:53:8b:c3:70:53:24:c7:a9:eb:8b:5f:fd:11:d0:06:4d:
+ c4:0e:ec:27:c7:09:88:f9:6e:fa:e2:ba:13:37:f8:e1:39:6b:
+ b4:b3:49:eb:13:58:38:e9:51:71:1e:fa:f1:29:7e:56:ad:43:
+ 03:80:61:d3:85:81:67:34:4b:a1:12:f0:2c:6f:3a:6c:b9:e2:
+ 51:a5:4f:95:5a:07:fe:c6:77:e1:5a:2b:b6:da:26:23:98:35:
+ 96:25:66:34:79:87:66:13:9a:34:56:57:49:e0:4e:b2:63:82:
+ 93:c3:9e:a0:5b:b5:fe:52:43:13:4d:cb:d4:25:e2:5d:a9:39:
+ b9:0e:18:4b:5d:96:b5:4e:20:05:ea:f5:01:d4:5c:93:d3:3f:
+ 76:5d:19:75:8d:28:d8:47:0c:7e:59:6f:16:6b:95:aa:7e:3c:
+ 0c:36:53:0f:03:40:63:27:fb:53:53:e9:52:73:9a:05:d8:26:
+ 5f:92:9d:37:85:b5:04:0f:2c:f6:5d:fe:68:f0:1b:3a:d9:ea:
+ cd:51:52:2c:6f:9d:5e:ed:c5:8c:e7:c0:43:bd:11:46:89:d7:
+ 86:51:61:50:da:b6:6a:e3:1e:88:47:3d:db:8b:2a:29:a2:ab:
+ 34:8e:08:4b:14:db:ab:64:99:71:ef:18:a0:4b:aa:3b:f0:85:
+ e3:81:c2:f6
+-----BEGIN CERTIFICATE-----
+MIIDwzCCAqugAwIBAgIBADANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJLUjEO
+MAwGA1UECAwFU2VvdWwxEDAOBgNVBAoMB1NhbXN1bmcxEzARBgNVBAsMClRpemVu
+IFRlc3QxGTAXBgNVBAMMEERSTSBUZXN0IFJvb3QgQ0ExGzAZBgkqhkiG9w0BCQEW
+DHR0QGdtYWlsLmNvbTAeFw0xNTA1MTMwMjQwMDhaFw0yNTA1MTAwMjQwMDhaMHwx
+CzAJBgNVBAYTAktSMQ4wDAYDVQQIDAVTZW91bDEQMA4GA1UECgwHU2Ftc3VuZzET
+MBEGA1UECwwKVGl6ZW4gVGVzdDEZMBcGA1UEAwwQRFJNIFRlc3QgUm9vdCBDQTEb
+MBkGCSqGSIb3DQEJARYMdHRAZ21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAwRnSr0Rm/f6AgGNGzOtg3YYtYdJC5Pk4ISc66xTC7ZB6c8qd
+RjOn9YMO5xMjABkQCPhyS6vCefgkrIP2lyPCyjZzEIftLRgM6tiXyo1wDUgKzgRs
+YADdEA122Q3hlJonmx2RMDTQGvS4gSYZcO+1qLCkajd53v5MEibIwOAR3Tm5QzAZ
+VatqrknlHMGcPsGNhA7sIATdiDeiUNB0AJnNaq7AuWi/IIBgIdLzrGpcMPu7JTLa
+/MtH3Vi3y7l168pu4LrZsJNFFExsTBvnrRq0entiaIN60oJVG5+6PX96mgECYtZ2
+ol1UjMyl0NPFoBZv3MzdFHNq707aYB8LcYsNbQIDAQABo1AwTjAdBgNVHQ4EFgQU
+M1bPin9wnGMrBda9P3gbdzyJc0YwHwYDVR0jBBgwFoAUM1bPin9wnGMrBda9P3gb
+dzyJc0YwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEABa5Ti8NwUyTH
+qeuLX/0R0AZNxA7sJ8cJiPlu+uK6Ezf44TlrtLNJ6xNYOOlRcR768Sl+Vq1DA4Bh
+04WBZzRLoRLwLG86bLniUaVPlVoH/sZ34VorttomI5g1liVmNHmHZhOaNFZXSeBO
+smOCk8OeoFu1/lJDE03L1CXiXak5uQ4YS12WtU4gBer1AdRck9M/dl0ZdY0o2EcM
+fllvFmuVqn48DDZTDwNAYyf7U1PpUnOaBdgmX5KdN4W1BA8s9l3+aPAbOtnqzVFS
+LG+dXu3FjOfAQ70RRonXhlFhUNq2auMeiEc924sqKaKrNI4ISxTbq2SZce8YoEuq
+O/CF44HC9g==
+-----END CERTIFICATE-----
diff --git a/test/sample_contents/KEYS/ro_test_second_ca.key b/test/sample_contents/KEYS/ro_test_second_ca.key
new file mode 100644
index 0000000..05a749e
--- /dev/null
+++ b/test/sample_contents/KEYS/ro_test_second_ca.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA4zCr9pSUh+DLByrZ5ts1ySz6OMB6Dim62nHs2iNGh1kTSBSW
+vdLWHVZVrARRhyBZ3b08/X20pNOUoh1y2a6iih15Y6XglE+CBo6J5klKfHfRxEHH
+SQH7FBncnVxUZq5sRyFY1xh/lmtBjfmhOc4+Pfks1009jYxOtbtfoQQ0FlDu6h1M
+wC2fGjpVVF3golpqsYf6MUdsqUgeiJc1no7Ex8NZ1SMJPqkPLAZDWZ0J94CTuRjj
+OCGW7G6z3cHKkEiaYwYPuB9aAxa7DI9zSRdRI8ckWoPlXAoAgN4gKqXBcuf42wK2
+YcXlXj2K1jOe8y8tNWTUdIJGcAehTJH68YOn2QIDAQABAoIBAQDU+T97O/WxGu24
+nlb+ruhQ2rUGlojU1hGvzbR3GTJ4luwYWhSlhgvqHJDbXIEA5zbXQxr1lu3MxftD
+rc+IeMkuKEsvOsS4w3/knaJwGqyU2c3u6KrkqdKxGT1S1sbYKxKd64jYusKAQ7OE
+YErfYZO/jOKYQnQ9SRZQDoKq8sHRV/EIrazP42tIFCc+kCBZvCaetIJz/jkQVOdb
+PYJTvOc2MjThNH23ysnYi48mGjMHzCMOPN1Jur378WiQ7uMHCOnQxbSuSkrGZ/or
+1ylC0y/VlYJhigIkv7hVekA4jczFmXNAylnFIgZlBdzLoAomlobP4GPlCzRsVYeu
+0lKK+LoBAoGBAPgpq0YI1sTOdxN1WbTOJgcQJmH9Z6tLkvkTg7yduiqLN5XC8701
+2L4i7u6MLWwPRJgNS3IX3i+ySjnGtP6HRGITiMhNrI9gUqiX+iI5rpg3l2nxADZJ
+AM7/MZEx6/ZDq5NpBgmXpL954SU/gdYg/uijqzqpu49GcAabjwoziAVpAoGBAOpd
+ccDa6EQBQp5Q3BK4M2M8Mec9MEGUlhh4+QOwvsFkjy/HzrqB0csL1eDWh+4rtXZi
+yAskVIFq6jRPH2G4ZRKeITvMZHPtYD8b7ASHv5VmgWZ6MnrcBknnNAbiZjMLNSiu
+lZMBt6Be4m5qlo8Bn0TtCMYFt5d6n2eac6AZIBDxAoGAAvzVcAlpNINb0aMnClM1
+B/68x486cUh+o3sFqf6oIBz+9VGch5mfW2KmR77uSQ/B/qaiUuRQq3hVBm8K/Ml6
+HEgp7Gdq/Wrmc9soisLxBCofK4pYO08TsGpIGXxlX9iety6bgQAPXrLD8CPcl0xc
+ZUabKCCk/muVq66xwSivqYkCgYAR1006ji+SRbpJjQRD1Ivs6P8viEPtKh+G+2aR
+dln/JOWVkJNXNVzAJUWB2TL92Yv12C08U+au93Gey8sqyDvBgBItmDCpdo+WHk0I
+R0E5YVVGdNT071z3MUePopp/FkJUt32hdEcDSVXZa/nMJyZ1u8moMXU5bddGrsZQ
+kLkVMQKBgCrajIe8MbVcwW5uuK66utjyKTcoGWZVew4/uCXwaZ0bO8yboLt2PCGm
+GqWSCVMqZaOJ08hU1ZArxemi61tFue12B/e6gYqBbFsJphE+9PnxtxcwH8Mope9M
+fV3d3LGBITtMMvopeRmWNFK1lNBZnmbp4gnvc2smv/RlYxET1j+8
+-----END RSA PRIVATE KEY-----
diff --git a/test/sample_contents/KEYS/ro_test_second_ca.pem b/test/sample_contents/KEYS/ro_test_second_ca.pem
new file mode 100644
index 0000000..0fc58f5
--- /dev/null
+++ b/test/sample_contents/KEYS/ro_test_second_ca.pem
@@ -0,0 +1,80 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=KR, ST=Seoul, O=Samsung, OU=Tizen Test, CN=DRM Test Root CA/emailAddress=tt@gmail.com
+ Validity
+ Not Before: May 13 02:43:49 2015 GMT
+ Not After : May 10 02:43:49 2025 GMT
+ Subject: C=KR, ST=Seoul, O=Samsung, OU=Tizen Test, CN=DRM Test Second CA/emailAddress=tt@gmail.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:e3:30:ab:f6:94:94:87:e0:cb:07:2a:d9:e6:db:
+ 35:c9:2c:fa:38:c0:7a:0e:29:ba:da:71:ec:da:23:
+ 46:87:59:13:48:14:96:bd:d2:d6:1d:56:55:ac:04:
+ 51:87:20:59:dd:bd:3c:fd:7d:b4:a4:d3:94:a2:1d:
+ 72:d9:ae:a2:8a:1d:79:63:a5:e0:94:4f:82:06:8e:
+ 89:e6:49:4a:7c:77:d1:c4:41:c7:49:01:fb:14:19:
+ dc:9d:5c:54:66:ae:6c:47:21:58:d7:18:7f:96:6b:
+ 41:8d:f9:a1:39:ce:3e:3d:f9:2c:d7:4d:3d:8d:8c:
+ 4e:b5:bb:5f:a1:04:34:16:50:ee:ea:1d:4c:c0:2d:
+ 9f:1a:3a:55:54:5d:e0:a2:5a:6a:b1:87:fa:31:47:
+ 6c:a9:48:1e:88:97:35:9e:8e:c4:c7:c3:59:d5:23:
+ 09:3e:a9:0f:2c:06:43:59:9d:09:f7:80:93:b9:18:
+ e3:38:21:96:ec:6e:b3:dd:c1:ca:90:48:9a:63:06:
+ 0f:b8:1f:5a:03:16:bb:0c:8f:73:49:17:51:23:c7:
+ 24:5a:83:e5:5c:0a:00:80:de:20:2a:a5:c1:72:e7:
+ f8:db:02:b6:61:c5:e5:5e:3d:8a:d6:33:9e:f3:2f:
+ 2d:35:64:d4:74:82:46:70:07:a1:4c:91:fa:f1:83:
+ a7:d9
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ BC:86:10:C1:9C:17:32:04:67:03:20:E0:C0:6D:FE:76:60:2A:86:03
+ X509v3 Authority Key Identifier:
+ keyid:33:56:CF:8A:7F:70:9C:63:2B:05:D6:BD:3F:78:1B:77:3C:89:73:46
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: sha256WithRSAEncryption
+ 06:fc:3f:04:a1:6d:39:1a:07:2a:a3:b1:96:be:40:19:41:3d:
+ 33:8e:60:3d:3a:e8:24:57:0a:0c:fc:da:8b:c2:a0:1b:0f:66:
+ 07:1f:af:65:73:71:5e:b7:17:3a:8a:b9:e7:a2:b7:4a:cc:6a:
+ b9:23:66:42:e9:60:e3:2e:10:55:48:f7:06:ce:8a:eb:e1:e7:
+ 97:14:81:e5:91:e3:6c:b2:85:ce:8e:34:b6:2c:d1:63:62:ff:
+ 06:82:65:04:3f:63:9b:da:b5:1b:9a:bc:22:de:78:e1:32:ed:
+ 83:e4:77:66:3a:0c:98:ce:80:08:ab:98:c6:25:bd:cf:82:76:
+ 31:98:8d:7b:7b:d1:3e:4e:ed:91:18:13:4a:b8:70:92:b0:19:
+ 2b:ee:95:be:33:ad:c3:6c:68:9d:8e:da:32:72:f0:42:12:ae:
+ c4:09:88:82:74:84:aa:75:78:6d:92:e8:67:f5:26:ac:20:e1:
+ 83:00:f0:63:b2:91:ab:4d:0f:2b:13:84:9e:fd:c6:5a:e6:9d:
+ b9:f4:3b:fc:28:a0:a1:1c:a9:2e:48:77:3c:c7:8b:95:ee:c5:
+ 49:34:ff:1d:3e:16:ee:2b:68:ec:28:11:a3:a7:9e:38:c1:97:
+ 6f:7c:7a:3e:9a:d3:c9:74:7f:67:a8:50:27:32:0d:f5:5f:17:
+ 38:8d:43:f4
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIBATANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJLUjEO
+MAwGA1UECAwFU2VvdWwxEDAOBgNVBAoMB1NhbXN1bmcxEzARBgNVBAsMClRpemVu
+IFRlc3QxGTAXBgNVBAMMEERSTSBUZXN0IFJvb3QgQ0ExGzAZBgkqhkiG9w0BCQEW
+DHR0QGdtYWlsLmNvbTAeFw0xNTA1MTMwMjQzNDlaFw0yNTA1MTAwMjQzNDlaMH4x
+CzAJBgNVBAYTAktSMQ4wDAYDVQQIDAVTZW91bDEQMA4GA1UECgwHU2Ftc3VuZzET
+MBEGA1UECwwKVGl6ZW4gVGVzdDEbMBkGA1UEAwwSRFJNIFRlc3QgU2Vjb25kIENB
+MRswGQYJKoZIhvcNAQkBFgx0dEBnbWFpbC5jb20wggEiMA0GCSqGSIb3DQEBAQUA
+A4IBDwAwggEKAoIBAQDjMKv2lJSH4MsHKtnm2zXJLPo4wHoOKbracezaI0aHWRNI
+FJa90tYdVlWsBFGHIFndvTz9fbSk05SiHXLZrqKKHXljpeCUT4IGjonmSUp8d9HE
+QcdJAfsUGdydXFRmrmxHIVjXGH+Wa0GN+aE5zj49+SzXTT2NjE61u1+hBDQWUO7q
+HUzALZ8aOlVUXeCiWmqxh/oxR2ypSB6IlzWejsTHw1nVIwk+qQ8sBkNZnQn3gJO5
+GOM4IZbsbrPdwcqQSJpjBg+4H1oDFrsMj3NJF1EjxyRag+VcCgCA3iAqpcFy5/jb
+ArZhxeVePYrWM57zLy01ZNR0gkZwB6FMkfrxg6fZAgMBAAGjUDBOMB0GA1UdDgQW
+BBS8hhDBnBcyBGcDIODAbf52YCqGAzAfBgNVHSMEGDAWgBQzVs+Kf3CcYysF1r0/
+eBt3PIlzRjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAG/D8EoW05
+Ggcqo7GWvkAZQT0zjmA9OugkVwoM/NqLwqAbD2YHH69lc3Fetxc6irnnordKzGq5
+I2ZC6WDjLhBVSPcGzorr4eeXFIHlkeNssoXOjjS2LNFjYv8GgmUEP2Ob2rUbmrwi
+3njhMu2D5HdmOgyYzoAIq5jGJb3PgnYxmI17e9E+Tu2RGBNKuHCSsBkr7pW+M63D
+bGidjtoycvBCEq7ECYiCdISqdXhtkuhn9SasIOGDAPBjspGrTQ8rE4Se/cZa5p25
+9Dv8KKChHKkuSHc8x4uV7sVJNP8dPhbuK2jsKBGjp544wZdvfHo+mtPJdH9nqFAn
+Mg31Xxc4jUP0
+-----END CERTIFICATE-----
diff --git a/test/sample_contents/KEYS/ro_test_signer.key b/test/sample_contents/KEYS/ro_test_signer.key
new file mode 100644
index 0000000..d4c36e7
--- /dev/null
+++ b/test/sample_contents/KEYS/ro_test_signer.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAxc8RvqYNWHogbQC6MOzMgieL3vkgadUZoK8rDQ2gV9z6HTiW
+ttYPuMaCT9l5DQubE+UZb8VDLwlAx+R6o0mexZB0c+Q2lR5HXi2eCnPoCfz/4i9z
+0lHPu+Q2x3M2LIYUgP45t+WXVgeLNStBIWmns8xlF410ARFFkdvzb7ZKwq0IYHSE
+XfeJi3pJTbNW0aX1G/2tEYgNg3XT1OYfEKSBlIHHzZiMIU4s9fRCJi77H+Khu6s9
+CvpR6R6qIkVNAJHlT2AW36aiOxpHvKFXb/L0w3K9s/VXWTAPD2iEFUsDUIZMjAgg
+nBXTR2BWKr9j6XQLje+WwJ/qV7TRgjSqxMVawwIDAQABAoIBAQCRfv7RWXhlhOcG
+5ksNo4/FiGsUZfBWh/1iuJWU81nmZs694ZrR/1/vDGxbaV3ln4zAtHniQZlqJoc0
+wLUIGCWlsdxGRi1zv6LE/g7KJ3kcp7BbYYXyxGRlErbMO800MKcyPkycHE8VY1Uc
+laVBe2J0GLqe+VfDVT3zzHIh0FbrG2oAMDoFgEaROLHVCzeV2Awu2Awh8XLJiiPM
+VezRT2AmXHSK1pe6GehgVzU00OCdQ4dwmRHA0FPatOGKcMt+oVGsg1CaCEKu+vSJ
+qF1v6n0lSGrmNMy2Cj+g/TnSJx1CvrpHReJAzyd5KDsI2n9DPHAuJSqHHiO271nc
+sVTIoSbZAoGBAOTKKyp3PUkbS5KuOpgv8XItha/ZvlD2fR5PB+q8+oqVe+lHCk9E
+0+zuKnLAWOk+41IiIp+dTyuyMH+B0NbZ0p47jbCJzqtRRPtZss0LSE3UR8Rq43bW
+AzeHJYNSoF1shh4Yvo3mxnlXu2Ov25B0gK3Pm65NbyHW2aXpubOmsHn3AoGBAN1V
+pOEQa36PQPMqb2vOcE59SW+iz36k+zrWybGgBldX64dnHad6whcQDyi3sFiS1Dzh
+BzwnXvr4QWNwPNv90af8swjQGdLLXNLPzlYXqZxiGReCpkc/cX06ioXE3ZSNVhNo
+ky/BqQ6uuSHIFTAaQyFF9cHXCxACyUTn7ToNnRKVAoGACKvw/ucOF5tFPgYEiogm
+qqE3E/c403DERUXRkwAeruoDjE/5ABAnyC8uxLKtrAmKLC7HCS25NnrGg86zz7Dp
+3r17HVnbz3qBFtXLhSIMV4bYQYWboYFzFcO1lEipc2ENpE5jypUYqLi+jYS42bzQ
+s8XOrMiakbnG/hbhxwFmZvkCgYEAvrTQf+u58y5TdDGYF3ekZLymzb2msyRMI4J1
+/so3LILguaYrcube3ShFJ3w+QdMhc+MgbMAvombNUHSgu5yTTP769Bj6Zxo6PJo4
+2w1AYzJTFGLKCpGro48RU/kwQpMVG1v7liZzF+eMNINFXlECjmTNP9ud+ImuCeUc
+De007ZECgYEAk7hs5Co9FkqZ0mSDcwFbHaD4lrLNOnoImplGTOt6UoQITEq+5UiF
+P8E+NrDrQeZ2n8VoxYmhL76X2EqzVa02kj6N+zmVSaJtnJlq3plTVbQjMZUogDUi
+cx2Ro24xMfwYzHtYw8Ctcycc+MM50k88IpWCt3X4wRcG7RSFjNSMpSk=
+-----END RSA PRIVATE KEY-----
diff --git a/test/sample_contents/KEYS/ro_test_signer.pem b/test/sample_contents/KEYS/ro_test_signer.pem
new file mode 100644
index 0000000..ec378a5
--- /dev/null
+++ b/test/sample_contents/KEYS/ro_test_signer.pem
@@ -0,0 +1,83 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2 (0x2)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=KR, ST=Seoul, O=Samsung, OU=Tizen Test, CN=DRM Test Second CA/emailAddress=tt@gmail.com
+ Validity
+ Not Before: May 13 02:44:59 2015 GMT
+ Not After : May 10 02:44:59 2025 GMT
+ Subject: C=KR, ST=Seoul, O=Samsung, OU=Tizen Test, CN=DRM Test Signer/emailAddress=tt@gmail.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c5:cf:11:be:a6:0d:58:7a:20:6d:00:ba:30:ec:
+ cc:82:27:8b:de:f9:20:69:d5:19:a0:af:2b:0d:0d:
+ a0:57:dc:fa:1d:38:96:b6:d6:0f:b8:c6:82:4f:d9:
+ 79:0d:0b:9b:13:e5:19:6f:c5:43:2f:09:40:c7:e4:
+ 7a:a3:49:9e:c5:90:74:73:e4:36:95:1e:47:5e:2d:
+ 9e:0a:73:e8:09:fc:ff:e2:2f:73:d2:51:cf:bb:e4:
+ 36:c7:73:36:2c:86:14:80:fe:39:b7:e5:97:56:07:
+ 8b:35:2b:41:21:69:a7:b3:cc:65:17:8d:74:01:11:
+ 45:91:db:f3:6f:b6:4a:c2:ad:08:60:74:84:5d:f7:
+ 89:8b:7a:49:4d:b3:56:d1:a5:f5:1b:fd:ad:11:88:
+ 0d:83:75:d3:d4:e6:1f:10:a4:81:94:81:c7:cd:98:
+ 8c:21:4e:2c:f5:f4:42:26:2e:fb:1f:e2:a1:bb:ab:
+ 3d:0a:fa:51:e9:1e:aa:22:45:4d:00:91:e5:4f:60:
+ 16:df:a6:a2:3b:1a:47:bc:a1:57:6f:f2:f4:c3:72:
+ bd:b3:f5:57:59:30:0f:0f:68:84:15:4b:03:50:86:
+ 4c:8c:08:20:9c:15:d3:47:60:56:2a:bf:63:e9:74:
+ 0b:8d:ef:96:c0:9f:ea:57:b4:d1:82:34:aa:c4:c5:
+ 5a:c3
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 1A:5E:D1:3E:1C:C6:7F:39:CD:43:39:CF:44:BA:8C:7B:47:65:4A:33
+ X509v3 Authority Key Identifier:
+ keyid:BC:86:10:C1:9C:17:32:04:67:03:20:E0:C0:6D:FE:76:60:2A:86:03
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 53:8c:af:93:96:ff:8e:2b:1b:1e:6f:63:47:bd:b7:83:af:1b:
+ 20:8f:66:9b:cf:f2:98:5b:3d:31:96:6f:d1:de:4e:bd:16:c8:
+ f7:ef:4c:14:21:fe:91:a3:11:75:1a:6b:6a:77:2b:de:1f:61:
+ 0c:e3:0c:35:c6:74:78:f6:0f:53:be:31:b5:5f:ff:19:63:c1:
+ 1f:c5:81:36:ca:d3:02:10:13:26:e0:d4:cc:50:6a:5b:95:ab:
+ a2:86:8a:81:d4:70:d7:e8:cc:fd:30:8c:15:b4:21:ce:59:1d:
+ d0:cd:01:76:b1:a0:e4:db:0c:39:0b:a3:61:75:92:c8:95:1b:
+ 87:a8:32:9c:fe:09:ed:51:f3:dc:88:c8:99:6d:82:06:db:93:
+ 63:1e:54:f2:1a:4f:10:03:6c:f4:27:26:8a:2b:1b:42:73:cb:
+ 6a:35:42:47:62:92:8b:7a:99:32:d6:aa:15:fa:7c:3d:6e:30:
+ 92:41:fe:05:d3:3a:66:3f:a4:bd:e6:48:fc:a6:3d:74:4a:74:
+ 06:e9:8b:a5:7e:da:8f:16:75:e1:e9:b7:61:d9:b7:80:6e:96:
+ e7:17:3a:da:c9:7b:0a:6e:bc:a8:81:a3:08:4d:90:76:50:40:
+ 6d:c2:6b:fa:50:a7:ad:49:0f:7b:d4:c0:fd:df:70:da:30:fb:
+ 13:ca:d0:a7
+-----BEGIN CERTIFICATE-----
+MIID7zCCAtegAwIBAgIBAjANBgkqhkiG9w0BAQsFADB+MQswCQYDVQQGEwJLUjEO
+MAwGA1UECAwFU2VvdWwxEDAOBgNVBAoMB1NhbXN1bmcxEzARBgNVBAsMClRpemVu
+IFRlc3QxGzAZBgNVBAMMEkRSTSBUZXN0IFNlY29uZCBDQTEbMBkGCSqGSIb3DQEJ
+ARYMdHRAZ21haWwuY29tMB4XDTE1MDUxMzAyNDQ1OVoXDTI1MDUxMDAyNDQ1OVow
+ezELMAkGA1UEBhMCS1IxDjAMBgNVBAgMBVNlb3VsMRAwDgYDVQQKDAdTYW1zdW5n
+MRMwEQYDVQQLDApUaXplbiBUZXN0MRgwFgYDVQQDDA9EUk0gVGVzdCBTaWduZXIx
+GzAZBgkqhkiG9w0BCQEWDHR0QGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAMXPEb6mDVh6IG0AujDszIIni975IGnVGaCvKw0NoFfc+h04
+lrbWD7jGgk/ZeQ0LmxPlGW/FQy8JQMfkeqNJnsWQdHPkNpUeR14tngpz6An8/+Iv
+c9JRz7vkNsdzNiyGFID+Obfll1YHizUrQSFpp7PMZReNdAERRZHb82+2SsKtCGB0
+hF33iYt6SU2zVtGl9Rv9rRGIDYN109TmHxCkgZSBx82YjCFOLPX0QiYu+x/iobur
+PQr6UekeqiJFTQCR5U9gFt+mojsaR7yhV2/y9MNyvbP1V1kwDw9ohBVLA1CGTIwI
+IJwV00dgViq/Y+l0C43vlsCf6le00YI0qsTFWsMCAwEAAaN7MHkwCQYDVR0TBAIw
+ADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUw
+HQYDVR0OBBYEFBpe0T4cxn85zUM5z0S6jHtHZUozMB8GA1UdIwQYMBaAFLyGEMGc
+FzIEZwMg4MBt/nZgKoYDMA0GCSqGSIb3DQEBCwUAA4IBAQBTjK+Tlv+OKxseb2NH
+vbeDrxsgj2abz/KYWz0xlm/R3k69Fsj370wUIf6RoxF1GmtqdyveH2EM4ww1xnR4
+9g9TvjG1X/8ZY8EfxYE2ytMCEBMm4NTMUGpblauihoqB1HDX6Mz9MIwVtCHOWR3Q
+zQF2saDk2ww5C6NhdZLIlRuHqDKc/gntUfPciMiZbYIG25NjHlTyGk8QA2z0JyaK
+KxtCc8tqNUJHYpKLepky1qoV+nw9bjCSQf4F0zpmP6S95kj8pj10SnQG6YulftqP
+FnXh6bdh2beAbpbnFzrayXsKbryogaMITZB2UEBtwmv6UKetSQ971MD933DaMPsT
+ytCn
+-----END CERTIFICATE-----
diff --git a/test/sample_contents/RO/38EIfBurLJ-1.0.2.cert_chain_invalid.ro b/test/sample_contents/RO/38EIfBurLJ-1.0.2.cert_chain_invalid.ro
new file mode 100644
index 0000000..471e08f
--- /dev/null
+++ b/test/sample_contents/RO/38EIfBurLJ-1.0.2.cert_chain_invalid.ro
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<TizenLicense>
+<LicenseInfo>
+ <version>2.0</version>
+ <uid>3bf1c4f12d79276156ad1ad6d2412be0695333c98607b63d1ce33fed20953d53fd4bc20643fea7ede212d911de542c1cec700745a9eb094a4d8851fca2f8e6fb</uid>
+</LicenseInfo>
+<ContentInfo>
+ <cid>38EIfBurLJ-1.0.2</cid>
+</ContentInfo>
+<KeyInfo>
+ <CipherValue>sQNPMMhSRX6dolIlLqmbKyU28Y0E0UzjloHZmLvXfso=</CipherValue>
+</KeyInfo>
+<DeviceInfo>
+ <DUID>njkbucn1dogaw</DUID>
+</DeviceInfo>
+<CertificateChain>
+ <Certificate>MIICiDCCAfGgAwIBAgIGAT3uVWhhMA0GCSqGSIb3DQEBBQUAMIGEMQswCQYDVQQGEwJLUjEOMAwGA1UECAwFU3V3b24xDjAMBgNVBAcMBVN1d29uMRYwFAYDVQQKDA1UaXplbiBUZXN0IENBMSAwHgYDVQQLDBdUaXplbiBEZXZlbG9wZXIgVGVzdCBDQTEbMBkGA1UEAwwSVGl6ZW4gRGV2ZWxvcGVyIENBMB4XDTEzMDQwOTEwMjY0N1oXDTQwMDgyNTEwMjY0NlowgYkxCzAJBgNVBAYTAktSMREwDwYDVQQIDAhLeXVuZy1naTEOMAwGA1UEBwwFU3V3b24xEDAOBgNVBAoMB1NhbXN1bmcxDDAKBgNVBAsMA1NQRzEnMCUGCSqGSIb3DQEJARYYc3VuZ2d1bi5qdW5nQHNhbXN1bmcuY29tMQ4wDAYDVQQDDAVGdEFwcDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAg43VXwzDa498f/+JiD38kDqiQ0Wx7/nEciwa2pktcna8KwSSUYIghExLZmQLBfudkxBpDeq+iEQzFm5QtSrH3KwJX6Da/PYTS3W7C4XdrbAWShPkSVyUp86P7u2Q+dwoAdPfqANm7DdTxQ4BUdtNtYcATQ9PHIu0Dk7OACBLb1kCAwEAATANBgkqhkiG9w0BAQUFAAOBgQCe9h4VRqMmU+7OH8BHJiIwnbdvfWnyGBjVQ4BrcybeTu6A2IgTibY4n6eelW2gFqxozI+fl5hW8wCRQNyDO2mef/WfopkJGbafpRv3eJfT2gKjJHRJEvaXutD3cPfvvOvzmMw0YijII3KhzIrbi3Fekg52nLkRZKHrqkQQvQfsOA==<Certificate>
+ <Certificate>MIICpzCCAhCgAwIBAgIJAKzDjmEF+1OXMA0GCSqGSIb3DQEBBQUAMIGTMQswCQYDVQQGEwJLUjEOMAwGA1UECAwFU3V3b24xDjAMBgNVBAcMBVN1d29uMRYwFAYDVQQKDA1UaXplbiBUZXN0IENBMSUwIwYDVQQLDBxUaXplbiBUZXN0IERldmVsb3BlciBSb290IENBMSUwIwYDVQQDDBxUaXplbiBUZXN0IERldmVsb3BlciBSb290IENBMB4XDTEyMTAyOTEzMDEyMloXDTIyMTAyNzEzMDEyMlowgYQxCzAJBgNVBAYTAktSMQ4wDAYDVQQIDAVTdXdvbjEOMAwGA1UEBwwFU3V3b24xFjAUBgNVBAoMDVRpemVuIFRlc3QgQ0ExIDAeBgNVBAsMF1RpemVuIERldmVsb3BlciBUZXN0IENBMRswGQYDVQQDDBJUaXplbiBEZXZlbG9wZXIgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMyG0DSTHBgalQo1seDKxpCU61gji+QQlxQkPQOvBrmuF6Z90zFCprTtg2sRjTLCNoRd75+VCCHuKGcrD27t7hwAekusPrpzdsq5QoBMvNjGDM22lC45PJ4d86DEDY4erxeJ5aSQxqbfXK4pKe9NwxdkKuA8dTYZM1UcmhXs7YALAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEACbr/OPNMJ+Ejrxfm/YjCiRPpjJLnwXS2IDtitbxot6bEdZkZvOFXOC0Ca4GT+jtvOcSlU7tM3Mdd1MrKe1kkoVd1vhCV8V4CK3/DPj8aN3rxfMfQitA6XMDcxzhsyMWz56OdifX50dvS/G/ad+kGhNhOOEKSE8zUyEDCGwqkfXk=</Certificate>
+</CertificateChain>
+<SignatureValue>FBUyG3BwR4TOb7EiKcTUTOxwDKdG79bqCwQ8XuROaqPcgdop8vL8zVuKSAvG0zipM2BIh9Ko6z/Q6fcMnIcRTSopcgdE9S/of+zLvuzjGhfy627Jyl7EqSJdSbFgorjrK05xk4fZ8FscplnUKjmWCs6/COqf8uZfxAtFjjtQbW4=</SignatureValue>
+</TizenLicense>
diff --git a/test/sample_contents/RO/38EIfBurLJ-1.0.2.cert_invalid.ro b/test/sample_contents/RO/38EIfBurLJ-1.0.2.cert_invalid.ro
new file mode 100644
index 0000000..66bdc0d
--- /dev/null
+++ b/test/sample_contents/RO/38EIfBurLJ-1.0.2.cert_invalid.ro
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<TizenLicense>
+<LicenseInfo>
+ <version>2.0</version>
+ <uid>3bf1c4f12d79276156ad1ad6d2412be0695333c98607b63d1ce33fed20953d53fd4bc20643fea7ede212d911de542c1cec700745a9eb094a4d8851fca2f8e6fb</uid>
+</LicenseInfo>
+<ContentInfo>
+ <cid>38EIfBurLJ-1.0.2</cid>
+</ContentInfo>
+<KeyInfo>
+ <CipherValue>sQNPMMhSRX6dolIlLqmbKyU28Y0E0UzjloHZmLvXfso=</CipherValue>
+</KeyInfo>
+<DeviceInfo>
+ <DUID>njkbucn1dogaw</DUID>
+</DeviceInfo>
+<CertificateChain>
+ <Certificate>MIIEXDCCA0SgAwIBAgIBRzANBgkqhkiG9w0BQUFADCBgzELAkGA1UEBhMS1IxHDAaBgNBAoTE1NhbXNbmcgRWxlY3Rb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTExMDIxMTAzMTAzMFoXDTMxMDIwNjAzMTAzMFowaDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxHjAcBgNVBAsTFU1lZGlhIFNvbHV0aW9uIENlbnRlcjEbMBkGA1UEAxMSRFJNKEFTVE9SRTItSU4tMDApMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhQisSmZqzucRFG8ckX4NtZgJSxdahP0OmKdRUoF3zxSrKXmiWj7fLRcj1puufn5TlikOVQmXwFPliqV90bUmOWHvc06Z8Sv2pdDas3foZ2pSDs+MZS1XTjhLkLTwkiNYFnzYepW2JueMF+EXZfWLKWCUK2sNvJux8dQcwhJIHZwIDAQABo4IBdzCCAXMwRgYIKwYBBQUHAQEEOjA4MDYGCCsGAQUFBzABhipodHRwOi8vcHViLm9zcHNlcnZlci5uZXQvc2VjdXJpdHkvc2NhL29jc3AwCQYDVR0TBAIwADCCAQ8GA1UdHwSCAQYwggECMIH/oHGgb4ZtbGRhcDovLzIxMC4xMTguNTcuMjk6Mzg5L0NOPWRwMSxPVT1NZWRpYSBTb2x1dGlvbiBDZW50ZXIsTz1TYW1zdW5nIEVsZWN0cm9uaWNzLEM9S1I/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdKKBiaSBhjCBgzEmMCQGA1UEAwwdU2Ftc3VuZyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxLjAsBgNVBAsMJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxHDAaBgNVBAoME1NhbXN1bmcgRWxlY3Ryb25pY3MxCzAJBgNVBAYTAktSMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQUFAAOCAQEAgX10I66EwTMdLNBiC6LRwFwDCaAbht6PsNeH0jvyph7d9gReNyJ0O15y+GFoFX3ta0K4xaf6qUcSg+8lRgkuMCxdMSqzN1e1ytmiLG/KQszXC2RtIEkSTe9DRh2u/Ozx5UwEL0ZO9MpTTlcti26MJ2dCbkfD2RHHqoQb5dJgUq2l8nAKVIWARjz3fdTdTbvqErTyUx7Oysch9nhu8OyymoLgoMI42kalgundQF6yYk+1XV34V72lM+z+9kak35pl9+j6XHA2S2HsyPN6JLzQfRxN05Kotyo5sHkNRX/fsTNe/xDOlDQccCf7uKZp9zwonBQB2XG6eZhI3hy7WLRb4Q==</Certificate>
+ <Certificate>MIIEFTCCAv2gAwIBAgIBADANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWl3Ryb25pY3MxjAsBgNVBAsTJVNbXN1bmcgQ2VydGlaWNhdGUgQXV0aGyaXR5IENlbnRyWwxKzApBgNVBAMTIlNhbXN1bmcgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDkxMTAyMDI1NDIwWhcNMjAxMDMwMDI1NDIwWjCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0bkji6Mggsv+hEUFd6FCLOUp0fXlqyGNzND/iD0KzeHfxiNkne55lpEpMQ8RR2Mk0oIMru8slnmlQe4G+Wi4ejuA+thpwtmcMHbiABk/1gb59agHEgiAWCYyGBtwTlNvjoC17pR7qTXp54LeDlinOVdqrr8KuDfxrD23IzkWoDFvTBxgh4Je86NMgG9CNoPcWgsFH2NSbmHlGMJGhQNyrzu9N8kT5RNdhZ3YA6y2Op1O2W61bCMoFaCxYuJBoF834umMX1QpMLdPyhDWvyRQF8eyrujk/lbxKFoUtoQdWo92wkH9fJzPbcrjzV08T0Zzv0ZMqI+cG1NUq4JGXJCztwIDAQABo4GMMIGJMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgH+MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUkjW5KAWZqeoa1Zc7sPtsrAhvbIUwHwYDVR0jBBgwFoAUdSvSt/cYuTKeXokzT+hjkv6fjVYwDQYJKoZIhvcNAQEFBQADggEBALoBA2T15qfVXYfaJaWeLNrM/68u7MeBX9zWfFLHIfjSxlJjyEGEJNEMPkNBS8XMXxG47+oRrTn9pHNVqkkA1g9TB7AJRSdiVhT0n5PfaUX73SBE2HzNOxB7dX6lUFbTtzjUNlJm40f4DBdkGEcmBMQZG8ffQbe50VS/e4e7DYX6bunxskf/9ROUcKwY43hFnP9S+RPE78QRsWkmfhxpNqXkJnQNodeNEJ3N05XmtNFjCdg+T67ldAHrZ6blYKC5J09p27T+Gp2WdOEDEKcgaOZQvgi6MC+mbxRlnIJKpAFM0y6TlrA/9leSX/aikqhcxiUf7mGKO0BfaCAbAQLkw5w=</Certificate>
+</CertificateChain>
+<SignatureValue>FBUyG3BwR4TOb7EiKcTUTOxwDKdG79bqCwQ8XuROaqPcgdop8vL8zVuKSAvG0zipM2BIh9Ko6z/Q6fcMnIcRTSopcgdE9S/of+zLvuzjGhfy627Jyl7EqSJdSbFgorjrK05xk4fZ8FscplnUKjmWCs6/COqf8uZfxAtFjjtQbW4=</SignatureValue>
+</TizenLicense>
diff --git a/test/sample_contents/RO/38EIfBurLJ-1.0.2.cert_only_selfsigned.ro b/test/sample_contents/RO/38EIfBurLJ-1.0.2.cert_only_selfsigned.ro
new file mode 100644
index 0000000..f2028c8
--- /dev/null
+++ b/test/sample_contents/RO/38EIfBurLJ-1.0.2.cert_only_selfsigned.ro
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<TizenLicense>
+<LicenseInfo>
+ <version>2.0</version>
+ <uid>3bf1c4f12d79276156ad1ad6d2412be0695333c98607b63d1ce33fed20953d53fd4bc20643fea7ede212d911de542c1cec700745a9eb094a4d8851fca2f8e6fb</uid>
+</LicenseInfo>
+<ContentInfo>
+ <cid>38EIfBurLJ-1.0.2</cid>
+</ContentInfo>
+<KeyInfo>
+ <CipherValue>sQNPMMhSRX6dolIlLqmbKyU28Y0E0UzjloHZmLvXfso=</CipherValue>
+</KeyInfo>
+<DeviceInfo>
+ <DUID>njkbucn1dogaw</DUID>
+</DeviceInfo>
+<CertificateChain>
+ <Certificate>MIIDhzCCAvCgAwIBAgIJAOuPXJj4AnB9MA0GCSqGSIb3DQEBBQUAMIGKMQswCQYDVQQGEwJLTzEOMAwGA1UECBMFU2VvdWwxDTALBgNVBAoTBElOS0ExIjAgBgNVBAsTGUZvciBUZXN0aW5nIFB1cnBvc2VzIE9ubHkxFzAVBgNVBAMTDklOS0EgVGVzdCBSb290MR8wHQYJKoZIhvcNAQkBFhBtcmF3c0BpbmthLmNvLmtyMB4XDTExMDMxODAwMzc0MVoXDTIxMDMxNTAwMzc0MVowgYoxCzAJBgNVBAYTAktPMQ4wDAYDVQQIEwVTZW91bDENMAsGA1UEChMESU5LQTEiMCAGA1UECxMZRm9yIFRlc3RpbmcgUHVycG9zZXMgT25seTEXMBUGA1UEAxMOSU5LQSBUZXN0IFJvb3QxHzAdBgkqhkiG9w0BCQEWEG1yYXdzQGlua2EuY28ua3IwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMVIStQdSk7U94YWO2J3fGZ8k7VyFWlSc78esNRmKVZbH6nNBSvQVNTzBF4kPrPJPzBUwUeXA53W14RYgqVHueQtJhRk79cwG9fF2Y5BtGkqT4e+4l8N7qpI/T6GpIDviPgA2KwEoeEUgJZMcTN4cu/Umm9mCw/i+SBbD6RDtdnLAgMBAAGjgfIwge8wHQYDVR0OBBYEFCUSehbI1Emm6ygKCzr7wSgRr7QUMIG/BgNVHSMEgbcwgbSAFCUSehbI1Emm6ygKCzr7wSgRr7QUoYGQpIGNMIGKMQswCQYDVQQGEwJLTzEOMAwGA1UECBMFU2VvdWwxDTALBgNVBAoTBElOS0ExIjAgBgNVBAsTGUZvciBUZXN0aW5nIFB1cnBvc2VzIE9ubHkxFzAVBgNVBAMTDklOS0EgVGVzdCBSb290MR8wHQYJKoZIhvcNAQkBFhBtcmF3c0BpbmthLmNvLmtyggkA649cmPgCcH0wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBfM+S3GxC+aMVUHthO8t7bDeDauraJQADYd0wfwU1t/tOz4v17esH6uFC7XT/yMktf3+p+u/E6apYvxlSEIaRIIRGpdCbBrGH7ujX3Az2anMzJWRwSV9YKaM13peYl7O7kH79kbgQ72646bDR0dU+rUF5UdPDhqvl97dgPLVoyFg==<Certificate>
+</CertificateChain>
+<SignatureValue>FBUyG3BwR4TOb7EiKcTUTOxwDKdG79bqCwQ8XuROaqPcgdop8vL8zVuKSAvG0zipM2BIh9Ko6z/Q6fcMnIcRTSopcgdE9S/of+zLvuzjGhfy627Jyl7EqSJdSbFgorjrK05xk4fZ8FscplnUKjmWCs6/COqf8uZfxAtFjjtQbW4=</SignatureValue>
+</TizenLicense>
diff --git a/test/sample_contents/RO/38EIfBurLJ-1.0.2.ro b/test/sample_contents/RO/38EIfBurLJ-1.0.2.ro
new file mode 100644
index 0000000..b7cebe3
--- /dev/null
+++ b/test/sample_contents/RO/38EIfBurLJ-1.0.2.ro
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<TizenLicense>
+<LicenseInfo>
+ <version>2.0</version>
+ <uid>3bf1c4f12d79276156ad1ad6d2412be0695333c98607b63d1ce33fed20953d53fd4bc20643fea7ede212d911de542c1cec700745a9eb094a4d8851fca2f8e6fb</uid>
+</LicenseInfo>
+<ContentInfo>
+ <cid>38EIfBurLJ-1.0.2</cid>
+</ContentInfo>
+<KeyInfo>
+ <CipherValue>sQNPMMhSRX6dolIlLqmbKyU28Y0E0UzjloHZmLvXfso=</CipherValue>
+</KeyInfo>
+<DeviceInfo>
+ <DUID>njkbucn1dogaw</DUID>
+</DeviceInfo>
+<CertificateChain>
+ <Certificate>MIIEXDCCA0SgAwIBAgIBRzANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTExMDIxMTAzMTAzMFoXDTMxMDIwNjAzMTAzMFowaDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxHjAcBgNVBAsTFU1lZGlhIFNvbHV0aW9uIENlbnRlcjEbMBkGA1UEAxMSRFJNKEFTVE9SRTItSU4tMDApMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhQisSmZqzucRFG8ckX4NtZgJSxdahP0OmKdRUoF3zxSrKXmiWj7fLRcj1puufn5TlikOVQmXwFPliqV90bUmOWHvc06Z8Sv2pdDas3foZ2pSDs+MZS1XTjhLkLTwkiNYFnzYepW2JueMF+EXZfWLKWCUK2sNvJux8dQcwhJIHZwIDAQABo4IBdzCCAXMwRgYIKwYBBQUHAQEEOjA4MDYGCCsGAQUFBzABhipodHRwOi8vcHViLm9zcHNlcnZlci5uZXQvc2VjdXJpdHkvc2NhL29jc3AwCQYDVR0TBAIwADCCAQ8GA1UdHwSCAQYwggECMIH/oHGgb4ZtbGRhcDovLzIxMC4xMTguNTcuMjk6Mzg5L0NOPWRwMSxPVT1NZWRpYSBTb2x1dGlvbiBDZW50ZXIsTz1TYW1zdW5nIEVsZWN0cm9uaWNzLEM9S1I/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdKKBiaSBhjCBgzEmMCQGA1UEAwwdU2Ftc3VuZyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxLjAsBgNVBAsMJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxHDAaBgNVBAoME1NhbXN1bmcgRWxlY3Ryb25pY3MxCzAJBgNVBAYTAktSMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQUFAAOCAQEAgX10I66EwTMdLNBiC6LRwFwDCaAbht6PsNeH0jvyph7d9gReNyJ0O15y+GFoFX3ta0K4xaf6qUcSg+8lRgkuMCxdMSqzN1e1ytmiLG/KQszXC2RtIEkSTe9DRh2u/Ozx5UwEL0ZO9MpTTlcti26MJ2dCbkfD2RHHqoQb5dJgUq2l8nAKVIWARjz3fdTdTbvqErTyUx7Oysch9nhu8OyymoLgoMI42kalgundQF6yYk+1XV34V72lM+z+9kak35pl9+j6XHA2S2HsyPN6JLzQfRxN05Kotyo5sHkNRX/fsTNe/xDOlDQccCf7uKZp9zwonBQB2XG6eZhI3hy7WLRb4Q==</Certificate>
+ <Certificate>MIIEFTCCAv2gAwIBAgIBADANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxKzApBgNVBAMTIlNhbXN1bmcgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDkxMTAyMDI1NDIwWhcNMjAxMDMwMDI1NDIwWjCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0bkji6Mggsv+hEUFd6FCLOUp0fXlqyGNzND/iD0KzeHfxiNkne55lpEpMQ8RR2Mk0oIMru8slnmlQe4G+Wi4ejuA+thpwtmcMHbiABk/1gb59agHEgiAWCYyGBtwTlNvjoC17pR7qTXp54LeDlinOVdqrr8KuDfxrD23IzkWoDFvTBxgh4Je86NMgG9CNoPcWgsFH2NSbmHlGMJGhQNyrzu9N8kT5RNdhZ3YA6y2Op1O2W61bCMoFaCxYuJBoF834umMX1QpMLdPyhDWvyRQF8eyrujk/lbxKFoUtoQdWo92wkH9fJzPbcrjzV08T0Zzv0ZMqI+cG1NUq4JGXJCztwIDAQABo4GMMIGJMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgH+MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUkjW5KAWZqeoa1Zc7sPtsrAhvbIUwHwYDVR0jBBgwFoAUdSvSt/cYuTKeXokzT+hjkv6fjVYwDQYJKoZIhvcNAQEFBQADggEBALoBA2T15qfVXYfaJaWeLNrM/68u7MeBX9zWfFLHIfjSxlJjyEGEJNEMPkNBS8XMXxG47+oRrTn9pHNVqkkA1g9TB7AJRSdiVhT0n5PfaUX73SBE2HzNOxB7dX6lUFbTtzjUNlJm40f4DBdkGEcmBMQZG8ffQbe50VS/e4e7DYX6bunxskf/9ROUcKwY43hFnP9S+RPE78QRsWkmfhxpNqXkJnQNodeNEJ3N05XmtNFjCdg+T67ldAHrZ6blYKC5J09p27T+Gp2WdOEDEKcgaOZQvgi6MC+mbxRlnIJKpAFM0y6TlrA/9leSX/aikqhcxiUf7mGKO0BfaCAbAQLkw5w=</Certificate>
+</CertificateChain>
+<SignatureValue>FBUyG3BwR4TOb7EiKcTUTOxwDKdG79bqCwQ8XuROaqPcgdop8vL8zVuKSAvG0zipM2BIh9Ko6z/Q6fcMnIcRTSopcgdE9S/of+zLvuzjGhfy627Jyl7EqSJdSbFgorjrK05xk4fZ8FscplnUKjmWCs6/COqf8uZfxAtFjjtQbW4=</SignatureValue>
+</TizenLicense>
diff --git a/test/sample_contents/RO/38EIfBurLJ-1.0.2.ro_template b/test/sample_contents/RO/38EIfBurLJ-1.0.2.ro_template
new file mode 100644
index 0000000..4f19377
--- /dev/null
+++ b/test/sample_contents/RO/38EIfBurLJ-1.0.2.ro_template
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<TizenLicense>
+<LicenseInfo>
+ <version>2.0</version>
+ <uid>3bf1c4f12d79276156ad1ad6d2412be0695333c98607b63d1ce33fed20953d53fd4bc20643fea7ede212d911de542c1cec700745a9eb094a4d8851fca2f8e6fb</uid>
+</LicenseInfo>
+<ContentInfo>
+ <cid>PLACE_HOLDER_FOR_CID</cid>
+</ContentInfo>
+<KeyInfo>
+ <CipherValue>sQNPMMhSRX6dolIlLqmbKyU28Y0E0UzjloHZmLvXfso=</CipherValue>
+</KeyInfo>
+<DeviceInfo>
+ <DUID>PLACE_HOLDER_FOR_DUID</DUID>
+</DeviceInfo>
+<CertificateChain>
+ <Certificate>MIID7zCCAtegAwIBAgIBAjANBgkqhkiG9w0BAQsFADB+MQswCQYDVQQGEwJLUjEOMAwGA1UECAwFU2VvdWwxEDAOBgNVBAoMB1NhbXN1bmcxEzARBgNVBAsMClRpemVuIFRlc3QxGzAZBgNVBAMMEkRSTSBUZXN0IFNlY29uZCBDQTEbMBkGCSqGSIb3DQEJARYMdHRAZ21haWwuY29tMB4XDTE1MDUxMzAyNDQ1OVoXDTI1MDUxMDAyNDQ1OVowezELMAkGA1UEBhMCS1IxDjAMBgNVBAgMBVNlb3VsMRAwDgYDVQQKDAdTYW1zdW5nMRMwEQYDVQQLDApUaXplbiBUZXN0MRgwFgYDVQQDDA9EUk0gVGVzdCBTaWduZXIxGzAZBgkqhkiG9w0BCQEWDHR0QGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMXPEb6mDVh6IG0AujDszIIni975IGnVGaCvKw0NoFfc+h04lrbWD7jGgk/ZeQ0LmxPlGW/FQy8JQMfkeqNJnsWQdHPkNpUeR14tngpz6An8/+Ivc9JRz7vkNsdzNiyGFID+Obfll1YHizUrQSFpp7PMZReNdAERRZHb82+2SsKtCGB0hF33iYt6SU2zVtGl9Rv9rRGIDYN109TmHxCkgZSBx82YjCFOLPX0QiYu+x/ioburPQr6UekeqiJFTQCR5U9gFt+mojsaR7yhV2/y9MNyvbP1V1kwDw9ohBVLA1CGTIwIIJwV00dgViq/Y+l0C43vlsCf6le00YI0qsTFWsMCAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFBpe0T4cxn85zUM5z0S6jHtHZUozMB8GA1UdIwQYMBaAFLyGEMGcFzIEZwMg4MBt/nZgKoYDMA0GCSqGSIb3DQEBCwUAA4IBAQBTjK+Tlv+OKxseb2NHvbeDrxsgj2abz/KYWz0xlm/R3k69Fsj370wUIf6RoxF1GmtqdyveH2EM4ww1xnR49g9TvjG1X/8ZY8EfxYE2ytMCEBMm4NTMUGpblauihoqB1HDX6Mz9MIwVtCHOWR3QzQF2saDk2ww5C6NhdZLIlRuHqDKc/gntUfPciMiZbYIG25NjHlTyGk8QA2z0JyaKKxtCc8tqNUJHYpKLepky1qoV+nw9bjCSQf4F0zpmP6S95kj8pj10SnQG6YulftqPFnXh6bdh2beAbpbnFzrayXsKbryogaMITZB2UEBtwmv6UKetSQ971MD933DaMPsTytCn</Certificate>
+ <Certificate>MIIDxTCCAq2gAwIBAgIBATANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJLUjEOMAwGA1UECAwFU2VvdWwxEDAOBgNVBAoMB1NhbXN1bmcxEzARBgNVBAsMClRpemVuIFRlc3QxGTAXBgNVBAMMEERSTSBUZXN0IFJvb3QgQ0ExGzAZBgkqhkiG9w0BCQEWDHR0QGdtYWlsLmNvbTAeFw0xNTA1MTMwMjQzNDlaFw0yNTA1MTAwMjQzNDlaMH4xCzAJBgNVBAYTAktSMQ4wDAYDVQQIDAVTZW91bDEQMA4GA1UECgwHU2Ftc3VuZzETMBEGA1UECwwKVGl6ZW4gVGVzdDEbMBkGA1UEAwwSRFJNIFRlc3QgU2Vjb25kIENBMRswGQYJKoZIhvcNAQkBFgx0dEBnbWFpbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDjMKv2lJSH4MsHKtnm2zXJLPo4wHoOKbracezaI0aHWRNIFJa90tYdVlWsBFGHIFndvTz9fbSk05SiHXLZrqKKHXljpeCUT4IGjonmSUp8d9HEQcdJAfsUGdydXFRmrmxHIVjXGH+Wa0GN+aE5zj49+SzXTT2NjE61u1+hBDQWUO7qHUzALZ8aOlVUXeCiWmqxh/oxR2ypSB6IlzWejsTHw1nVIwk+qQ8sBkNZnQn3gJO5GOM4IZbsbrPdwcqQSJpjBg+4H1oDFrsMj3NJF1EjxyRag+VcCgCA3iAqpcFy5/jbArZhxeVePYrWM57zLy01ZNR0gkZwB6FMkfrxg6fZAgMBAAGjUDBOMB0GA1UdDgQWBBS8hhDBnBcyBGcDIODAbf52YCqGAzAfBgNVHSMEGDAWgBQzVs+Kf3CcYysF1r0/eBt3PIlzRjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAG/D8EoW05Ggcqo7GWvkAZQT0zjmA9OugkVwoM/NqLwqAbD2YHH69lc3Fetxc6irnnordKzGq5I2ZC6WDjLhBVSPcGzorr4eeXFIHlkeNssoXOjjS2LNFjYv8GgmUEP2Ob2rUbmrwi3njhMu2D5HdmOgyYzoAIq5jGJb3PgnYxmI17e9E+Tu2RGBNKuHCSsBkr7pW+M63DbGidjtoycvBCEq7ECYiCdISqdXhtkuhn9SasIOGDAPBjspGrTQ8rE4Se/cZa5p259Dv8KKChHKkuSHc8x4uV7sVJNP8dPhbuK2jsKBGjp544wZdvfHo+mtPJdH9nqFAnMg31Xxc4jUP0</Certificate>
+</CertificateChain>
+<SignatureValue>PLACE_HOLDER_FOR_SIGNATURE</SignatureValue>
+</TizenLicense>
diff --git a/test/sample_contents/RO/38EIfBurLJ-1.0.2.signature_invalid.ro b/test/sample_contents/RO/38EIfBurLJ-1.0.2.signature_invalid.ro
new file mode 100644
index 0000000..cd6e229
--- /dev/null
+++ b/test/sample_contents/RO/38EIfBurLJ-1.0.2.signature_invalid.ro
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<TizenLicense>
+<LicenseInfo>
+ <version>2.0</version>
+ <uid>3bf1c4f12d79276156ad1ad6d2412be0695333c98607b63d1ce33fed20953d53fd4bc20643fea7ede212d911de542c1cec700745a9eb094a4d8851fca2f8e6fb</uid>
+</LicenseInfo>
+<ContentInfo>
+ <cid>38EIfBurLJ-1.0.2</cid>
+</ContentInfo>
+<KeyInfo>
+ <CipherValue>sQNPMMhSRX6dolIlLqmbKyU28Y0E0UzjloHZmLvXfso=</CipherValue>
+</KeyInfo>
+<DeviceInfo>
+ <DUID>njkbucn1dogaw</DUID>
+</DeviceInfo>
+<CertificateChain>
+ <Certificate>MIIEXDCCA0SgAwIBAgIBRzANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTExMDIxMTAzMTAzMFoXDTMxMDIwNjAzMTAzMFowaDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxHjAcBgNVBAsTFU1lZGlhIFNvbHV0aW9uIENlbnRlcjEbMBkGA1UEAxMSRFJNKEFTVE9SRTItSU4tMDApMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhQisSmZqzucRFG8ckX4NtZgJSxdahP0OmKdRUoF3zxSrKXmiWj7fLRcj1puufn5TlikOVQmXwFPliqV90bUmOWHvc06Z8Sv2pdDas3foZ2pSDs+MZS1XTjhLkLTwkiNYFnzYepW2JueMF+EXZfWLKWCUK2sNvJux8dQcwhJIHZwIDAQABo4IBdzCCAXMwRgYIKwYBBQUHAQEEOjA4MDYGCCsGAQUFBzABhipodHRwOi8vcHViLm9zcHNlcnZlci5uZXQvc2VjdXJpdHkvc2NhL29jc3AwCQYDVR0TBAIwADCCAQ8GA1UdHwSCAQYwggECMIH/oHGgb4ZtbGRhcDovLzIxMC4xMTguNTcuMjk6Mzg5L0NOPWRwMSxPVT1NZWRpYSBTb2x1dGlvbiBDZW50ZXIsTz1TYW1zdW5nIEVsZWN0cm9uaWNzLEM9S1I/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdKKBiaSBhjCBgzEmMCQGA1UEAwwdU2Ftc3VuZyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxLjAsBgNVBAsMJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxHDAaBgNVBAoME1NhbXN1bmcgRWxlY3Ryb25pY3MxCzAJBgNVBAYTAktSMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQUFAAOCAQEAgX10I66EwTMdLNBiC6LRwFwDCaAbht6PsNeH0jvyph7d9gReNyJ0O15y+GFoFX3ta0K4xaf6qUcSg+8lRgkuMCxdMSqzN1e1ytmiLG/KQszXC2RtIEkSTe9DRh2u/Ozx5UwEL0ZO9MpTTlcti26MJ2dCbkfD2RHHqoQb5dJgUq2l8nAKVIWARjz3fdTdTbvqErTyUx7Oysch9nhu8OyymoLgoMI42kalgundQF6yYk+1XV34V72lM+z+9kak35pl9+j6XHA2S2HsyPN6JLzQfRxN05Kotyo5sHkNRX/fsTNe/xDOlDQccCf7uKZp9zwonBQB2XG6eZhI3hy7WLRb4Q==</Certificate>
+ <Certificate>MIIEFTCCAv2gAwIBAgIBADANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxKzApBgNVBAMTIlNhbXN1bmcgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDkxMTAyMDI1NDIwWhcNMjAxMDMwMDI1NDIwWjCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0bkji6Mggsv+hEUFd6FCLOUp0fXlqyGNzND/iD0KzeHfxiNkne55lpEpMQ8RR2Mk0oIMru8slnmlQe4G+Wi4ejuA+thpwtmcMHbiABk/1gb59agHEgiAWCYyGBtwTlNvjoC17pR7qTXp54LeDlinOVdqrr8KuDfxrD23IzkWoDFvTBxgh4Je86NMgG9CNoPcWgsFH2NSbmHlGMJGhQNyrzu9N8kT5RNdhZ3YA6y2Op1O2W61bCMoFaCxYuJBoF834umMX1QpMLdPyhDWvyRQF8eyrujk/lbxKFoUtoQdWo92wkH9fJzPbcrjzV08T0Zzv0ZMqI+cG1NUq4JGXJCztwIDAQABo4GMMIGJMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgH+MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUkjW5KAWZqeoa1Zc7sPtsrAhvbIUwHwYDVR0jBBgwFoAUdSvSt/cYuTKeXokzT+hjkv6fjVYwDQYJKoZIhvcNAQEFBQADggEBALoBA2T15qfVXYfaJaWeLNrM/68u7MeBX9zWfFLHIfjSxlJjyEGEJNEMPkNBS8XMXxG47+oRrTn9pHNVqkkA1g9TB7AJRSdiVhT0n5PfaUX73SBE2HzNOxB7dX6lUFbTtzjUNlJm40f4DBdkGEcmBMQZG8ffQbe50VS/e4e7DYX6bunxskf/9ROUcKwY43hFnP9S+RPE78QRsWkmfhxpNqXkJnQNodeNEJ3N05XmtNFjCdg+T67ldAHrZ6blYKC5J09p27T+Gp2WdOEDEKcgaOZQvgi6MC+mbxRlnIJKpAFM0y6TlrA/9leSX/aikqhcxiUf7mGKO0BfaCAbAQLkw5w=</Certificate>
+</CertificateChain>
+<SignatureValue>FFFyG3BwR4TOb7EiKcTUTOxwDKdG79bqCwQ8XuROaqPcgdop8vL8zVuKSAvG0zipM2BIh9Ko6z/Q6fcMnIcRTSopcgdE9S/of+zLvuzjGhfy627Jyl7EqSJdSbFgorjrK05xk4fZ8FscplnUKjmWCs6/COqf8uZfxAtFjjtQbW4=</SignatureValue>
+</TizenLicense>
diff --git a/test/sample_contents/RO/8SPXfqc6iL-1.0.0.ro b/test/sample_contents/RO/8SPXfqc6iL-1.0.0.ro
new file mode 100644
index 0000000..966c55e
--- /dev/null
+++ b/test/sample_contents/RO/8SPXfqc6iL-1.0.0.ro
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<TizenLicense>
+<LicenseInfo>
+ <version>2.0</version>
+ <uid>106bbf23987276b15ba5918798b7e57f2b9c121f401926113a18192aa3698b00d3e418075695e93c46f3a829759b44c55a9843d21c19c9d387619b855cf8af4f</uid>
+</LicenseInfo>
+<ContentInfo>
+ <cid>8SPXfqc6iL-1.0.0</cid>
+</ContentInfo>
+<KeyInfo>
+ <CipherValue>u4ddqCzER4GQutmwDNKU6RkPJGJbC0l6ro4diH/5lts=</CipherValue>
+</KeyInfo>
+<DeviceInfo>
+ <DUID>njkbucn1dogaw</DUID>
+</DeviceInfo>
+<CertificateChain>
+ <Certificate>MIIEXDCCA0SgAwIBAgIBRzANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTExMDIxMTAzMTAzMFoXDTMxMDIwNjAzMTAzMFowaDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxHjAcBgNVBAsTFU1lZGlhIFNvbHV0aW9uIENlbnRlcjEbMBkGA1UEAxMSRFJNKEFTVE9SRTItSU4tMDApMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhQisSmZqzucRFG8ckX4NtZgJSxdahP0OmKdRUoF3zxSrKXmiWj7fLRcj1puufn5TlikOVQmXwFPliqV90bUmOWHvc06Z8Sv2pdDas3foZ2pSDs+MZS1XTjhLkLTwkiNYFnzYepW2JueMF+EXZfWLKWCUK2sNvJux8dQcwhJIHZwIDAQABo4IBdzCCAXMwRgYIKwYBBQUHAQEEOjA4MDYGCCsGAQUFBzABhipodHRwOi8vcHViLm9zcHNlcnZlci5uZXQvc2VjdXJpdHkvc2NhL29jc3AwCQYDVR0TBAIwADCCAQ8GA1UdHwSCAQYwggECMIH/oHGgb4ZtbGRhcDovLzIxMC4xMTguNTcuMjk6Mzg5L0NOPWRwMSxPVT1NZWRpYSBTb2x1dGlvbiBDZW50ZXIsTz1TYW1zdW5nIEVsZWN0cm9uaWNzLEM9S1I/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdKKBiaSBhjCBgzEmMCQGA1UEAwwdU2Ftc3VuZyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxLjAsBgNVBAsMJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxHDAaBgNVBAoME1NhbXN1bmcgRWxlY3Ryb25pY3MxCzAJBgNVBAYTAktSMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQUFAAOCAQEAgX10I66EwTMdLNBiC6LRwFwDCaAbht6PsNeH0jvyph7d9gReNyJ0O15y+GFoFX3ta0K4xaf6qUcSg+8lRgkuMCxdMSqzN1e1ytmiLG/KQszXC2RtIEkSTe9DRh2u/Ozx5UwEL0ZO9MpTTlcti26MJ2dCbkfD2RHHqoQb5dJgUq2l8nAKVIWARjz3fdTdTbvqErTyUx7Oysch9nhu8OyymoLgoMI42kalgundQF6yYk+1XV34V72lM+z+9kak35pl9+j6XHA2S2HsyPN6JLzQfRxN05Kotyo5sHkNRX/fsTNe/xDOlDQccCf7uKZp9zwonBQB2XG6eZhI3hy7WLRb4Q==</Certificate>
+ <Certificate>MIIEFTCCAv2gAwIBAgIBADANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxKzApBgNVBAMTIlNhbXN1bmcgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDkxMTAyMDI1NDIwWhcNMjAxMDMwMDI1NDIwWjCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0bkji6Mggsv+hEUFd6FCLOUp0fXlqyGNzND/iD0KzeHfxiNkne55lpEpMQ8RR2Mk0oIMru8slnmlQe4G+Wi4ejuA+thpwtmcMHbiABk/1gb59agHEgiAWCYyGBtwTlNvjoC17pR7qTXp54LeDlinOVdqrr8KuDfxrD23IzkWoDFvTBxgh4Je86NMgG9CNoPcWgsFH2NSbmHlGMJGhQNyrzu9N8kT5RNdhZ3YA6y2Op1O2W61bCMoFaCxYuJBoF834umMX1QpMLdPyhDWvyRQF8eyrujk/lbxKFoUtoQdWo92wkH9fJzPbcrjzV08T0Zzv0ZMqI+cG1NUq4JGXJCztwIDAQABo4GMMIGJMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgH+MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUkjW5KAWZqeoa1Zc7sPtsrAhvbIUwHwYDVR0jBBgwFoAUdSvSt/cYuTKeXokzT+hjkv6fjVYwDQYJKoZIhvcNAQEFBQADggEBALoBA2T15qfVXYfaJaWeLNrM/68u7MeBX9zWfFLHIfjSxlJjyEGEJNEMPkNBS8XMXxG47+oRrTn9pHNVqkkA1g9TB7AJRSdiVhT0n5PfaUX73SBE2HzNOxB7dX6lUFbTtzjUNlJm40f4DBdkGEcmBMQZG8ffQbe50VS/e4e7DYX6bunxskf/9ROUcKwY43hFnP9S+RPE78QRsWkmfhxpNqXkJnQNodeNEJ3N05XmtNFjCdg+T67ldAHrZ6blYKC5J09p27T+Gp2WdOEDEKcgaOZQvgi6MC+mbxRlnIJKpAFM0y6TlrA/9leSX/aikqhcxiUf7mGKO0BfaCAbAQLkw5w=</Certificate>
+</CertificateChain>
+<SignatureValue>Bzcf8jboO0RxB4A8Q05ctqq1JIFguGrDzN1gLjVlvbXEDHxPOjfCEFTI0PQLVaTUkKl3f1FBjPc0dJpNt9jKYAw+YSyw2ynpfMavd5JNuv8NDTFedoOXw+eTHZFibxgfGJiev+z+RXNqZYE/P5RP3uxp1r2heB1K8b/J6RPCAA0=</SignatureValue>
+</TizenLicense>
diff --git a/test/sample_contents/RO/8SPXfqc6iL-1.0.0.signature_invalid.ro b/test/sample_contents/RO/8SPXfqc6iL-1.0.0.signature_invalid.ro
new file mode 100644
index 0000000..23f6961
--- /dev/null
+++ b/test/sample_contents/RO/8SPXfqc6iL-1.0.0.signature_invalid.ro
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<TizenLicense>
+<LicenseInfo>
+ <version>2.0</version>
+ <uid>106bbf23987276b15ba5918798b7e57f2b9c121f401926113a18192aa3698b00d3e418075695e93c46f3a829759b44c55a9843d21c19c9d387619b855cf8af4f</uid>
+</LicenseInfo>
+<ContentInfo>
+ <cid>8SPXfqc6iL-1.0.0</cid>
+</ContentInfo>
+<KeyInfo>
+ <CipherValue>u4ddqCzER4GQutmwDNKU6RkPJGJbC0l6ro4diH/5lts=</CipherValue>
+</KeyInfo>
+<DeviceInfo>
+ <DUID>njkbucn1dogaw</DUID>
+</DeviceInfo>
+<CertificateChain>
+ <Certificate>MIIEXDCCA0SgAwIBAgIBRzANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTExMDIxMTAzMTAzMFoXDTMxMDIwNjAzMTAzMFowaDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxHjAcBgNVBAsTFU1lZGlhIFNvbHV0aW9uIENlbnRlcjEbMBkGA1UEAxMSRFJNKEFTVE9SRTItSU4tMDApMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhQisSmZqzucRFG8ckX4NtZgJSxdahP0OmKdRUoF3zxSrKXmiWj7fLRcj1puufn5TlikOVQmXwFPliqV90bUmOWHvc06Z8Sv2pdDas3foZ2pSDs+MZS1XTjhLkLTwkiNYFnzYepW2JueMF+EXZfWLKWCUK2sNvJux8dQcwhJIHZwIDAQABo4IBdzCCAXMwRgYIKwYBBQUHAQEEOjA4MDYGCCsGAQUFBzABhipodHRwOi8vcHViLm9zcHNlcnZlci5uZXQvc2VjdXJpdHkvc2NhL29jc3AwCQYDVR0TBAIwADCCAQ8GA1UdHwSCAQYwggECMIH/oHGgb4ZtbGRhcDovLzIxMC4xMTguNTcuMjk6Mzg5L0NOPWRwMSxPVT1NZWRpYSBTb2x1dGlvbiBDZW50ZXIsTz1TYW1zdW5nIEVsZWN0cm9uaWNzLEM9S1I/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdKKBiaSBhjCBgzEmMCQGA1UEAwwdU2Ftc3VuZyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxLjAsBgNVBAsMJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxHDAaBgNVBAoME1NhbXN1bmcgRWxlY3Ryb25pY3MxCzAJBgNVBAYTAktSMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQUFAAOCAQEAgX10I66EwTMdLNBiC6LRwFwDCaAbht6PsNeH0jvyph7d9gReNyJ0O15y+GFoFX3ta0K4xaf6qUcSg+8lRgkuMCxdMSqzN1e1ytmiLG/KQszXC2RtIEkSTe9DRh2u/Ozx5UwEL0ZO9MpTTlcti26MJ2dCbkfD2RHHqoQb5dJgUq2l8nAKVIWARjz3fdTdTbvqErTyUx7Oysch9nhu8OyymoLgoMI42kalgundQF6yYk+1XV34V72lM+z+9kak35pl9+j6XHA2S2HsyPN6JLzQfRxN05Kotyo5sHkNRX/fsTNe/xDOlDQccCf7uKZp9zwonBQB2XG6eZhI3hy7WLRb4Q==</Certificate>
+ <Certificate>MIIEFTCCAv2gAwIBAgIBADANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxKzApBgNVBAMTIlNhbXN1bmcgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDkxMTAyMDI1NDIwWhcNMjAxMDMwMDI1NDIwWjCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0bkji6Mggsv+hEUFd6FCLOUp0fXlqyGNzND/iD0KzeHfxiNkne55lpEpMQ8RR2Mk0oIMru8slnmlQe4G+Wi4ejuA+thpwtmcMHbiABk/1gb59agHEgiAWCYyGBtwTlNvjoC17pR7qTXp54LeDlinOVdqrr8KuDfxrD23IzkWoDFvTBxgh4Je86NMgG9CNoPcWgsFH2NSbmHlGMJGhQNyrzu9N8kT5RNdhZ3YA6y2Op1O2W61bCMoFaCxYuJBoF834umMX1QpMLdPyhDWvyRQF8eyrujk/lbxKFoUtoQdWo92wkH9fJzPbcrjzV08T0Zzv0ZMqI+cG1NUq4JGXJCztwIDAQABo4GMMIGJMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgH+MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUkjW5KAWZqeoa1Zc7sPtsrAhvbIUwHwYDVR0jBBgwFoAUdSvSt/cYuTKeXokzT+hjkv6fjVYwDQYJKoZIhvcNAQEFBQADggEBALoBA2T15qfVXYfaJaWeLNrM/68u7MeBX9zWfFLHIfjSxlJjyEGEJNEMPkNBS8XMXxG47+oRrTn9pHNVqkkA1g9TB7AJRSdiVhT0n5PfaUX73SBE2HzNOxB7dX6lUFbTtzjUNlJm40f4DBdkGEcmBMQZG8ffQbe50VS/e4e7DYX6bunxskf/9ROUcKwY43hFnP9S+RPE78QRsWkmfhxpNqXkJnQNodeNEJ3N05XmtNFjCdg+T67ldAHrZ6blYKC5J09p27T+Gp2WdOEDEKcgaOZQvgi6MC+mbxRlnIJKpAFM0y6TlrA/9leSX/aikqhcxiUf7mGKO0BfaCAbAQLkw5w=</Certificate>
+</CertificateChain>
+<SignatureValue>BBBf8jboO0RxB4A8Q05ctqq1JIFguGrDzN1gLjVlvbXEDHxPOjfCEFTI0PQLVaTUkKl3f1FBjPc0dJpNt9jKYAw+YSyw2ynpfMavd5JNuv8NDTFedoOXw+eTHZFibxgfGJiev+z+RXNqZYE/P5RP3uxp1r2heB1K8b/J6RPCAA0=</SignatureValue>
+</TizenLicense>
diff --git a/test/sample_contents/RO/FightGuiIF-1.0.0.ro b/test/sample_contents/RO/FightGuiIF-1.0.0.ro
new file mode 100644
index 0000000..45e4401
--- /dev/null
+++ b/test/sample_contents/RO/FightGuiIF-1.0.0.ro
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<TizenLicense>
+<LicenseInfo>
+ <version>2.0</version>
+ <uid>f4bc06a9fd3cc17a80fbc005b5f0e3392b9c121f401926113a18192aa3698b00d3e418075695e93c46f3a829759b44c51002ec661b601ec5414304cc5d3fea47</uid>
+</LicenseInfo>
+<ContentInfo>
+ <cid>FightGuiIF-1.0.0</cid>
+</ContentInfo>
+<KeyInfo>
+ <CipherValue>NFqUKMP0RD+Gbc/FeB8jzumbxEWjMEcetOCvlg/eqbQ=</CipherValue>
+</KeyInfo>
+<DeviceInfo>
+ <DUID>njkbucn1dogaw</DUID>
+</DeviceInfo>
+<CertificateChain>
+ <Certificate>MIIEXDCCA0SgAwIBAgIBRzANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTExMDIxMTAzMTAzMFoXDTMxMDIwNjAzMTAzMFowaDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxHjAcBgNVBAsTFU1lZGlhIFNvbHV0aW9uIENlbnRlcjEbMBkGA1UEAxMSRFJNKEFTVE9SRTItSU4tMDApMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhQisSmZqzucRFG8ckX4NtZgJSxdahP0OmKdRUoF3zxSrKXmiWj7fLRcj1puufn5TlikOVQmXwFPliqV90bUmOWHvc06Z8Sv2pdDas3foZ2pSDs+MZS1XTjhLkLTwkiNYFnzYepW2JueMF+EXZfWLKWCUK2sNvJux8dQcwhJIHZwIDAQABo4IBdzCCAXMwRgYIKwYBBQUHAQEEOjA4MDYGCCsGAQUFBzABhipodHRwOi8vcHViLm9zcHNlcnZlci5uZXQvc2VjdXJpdHkvc2NhL29jc3AwCQYDVR0TBAIwADCCAQ8GA1UdHwSCAQYwggECMIH/oHGgb4ZtbGRhcDovLzIxMC4xMTguNTcuMjk6Mzg5L0NOPWRwMSxPVT1NZWRpYSBTb2x1dGlvbiBDZW50ZXIsTz1TYW1zdW5nIEVsZWN0cm9uaWNzLEM9S1I/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdKKBiaSBhjCBgzEmMCQGA1UEAwwdU2Ftc3VuZyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxLjAsBgNVBAsMJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxHDAaBgNVBAoME1NhbXN1bmcgRWxlY3Ryb25pY3MxCzAJBgNVBAYTAktSMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQUFAAOCAQEAgX10I66EwTMdLNBiC6LRwFwDCaAbht6PsNeH0jvyph7d9gReNyJ0O15y+GFoFX3ta0K4xaf6qUcSg+8lRgkuMCxdMSqzN1e1ytmiLG/KQszXC2RtIEkSTe9DRh2u/Ozx5UwEL0ZO9MpTTlcti26MJ2dCbkfD2RHHqoQb5dJgUq2l8nAKVIWARjz3fdTdTbvqErTyUx7Oysch9nhu8OyymoLgoMI42kalgundQF6yYk+1XV34V72lM+z+9kak35pl9+j6XHA2S2HsyPN6JLzQfRxN05Kotyo5sHkNRX/fsTNe/xDOlDQccCf7uKZp9zwonBQB2XG6eZhI3hy7WLRb4Q==</Certificate>
+ <Certificate>MIIEFTCCAv2gAwIBAgIBADANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxKzApBgNVBAMTIlNhbXN1bmcgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDkxMTAyMDI1NDIwWhcNMjAxMDMwMDI1NDIwWjCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0bkji6Mggsv+hEUFd6FCLOUp0fXlqyGNzND/iD0KzeHfxiNkne55lpEpMQ8RR2Mk0oIMru8slnmlQe4G+Wi4ejuA+thpwtmcMHbiABk/1gb59agHEgiAWCYyGBtwTlNvjoC17pR7qTXp54LeDlinOVdqrr8KuDfxrD23IzkWoDFvTBxgh4Je86NMgG9CNoPcWgsFH2NSbmHlGMJGhQNyrzu9N8kT5RNdhZ3YA6y2Op1O2W61bCMoFaCxYuJBoF834umMX1QpMLdPyhDWvyRQF8eyrujk/lbxKFoUtoQdWo92wkH9fJzPbcrjzV08T0Zzv0ZMqI+cG1NUq4JGXJCztwIDAQABo4GMMIGJMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgH+MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUkjW5KAWZqeoa1Zc7sPtsrAhvbIUwHwYDVR0jBBgwFoAUdSvSt/cYuTKeXokzT+hjkv6fjVYwDQYJKoZIhvcNAQEFBQADggEBALoBA2T15qfVXYfaJaWeLNrM/68u7MeBX9zWfFLHIfjSxlJjyEGEJNEMPkNBS8XMXxG47+oRrTn9pHNVqkkA1g9TB7AJRSdiVhT0n5PfaUX73SBE2HzNOxB7dX6lUFbTtzjUNlJm40f4DBdkGEcmBMQZG8ffQbe50VS/e4e7DYX6bunxskf/9ROUcKwY43hFnP9S+RPE78QRsWkmfhxpNqXkJnQNodeNEJ3N05XmtNFjCdg+T67ldAHrZ6blYKC5J09p27T+Gp2WdOEDEKcgaOZQvgi6MC+mbxRlnIJKpAFM0y6TlrA/9leSX/aikqhcxiUf7mGKO0BfaCAbAQLkw5w=</Certificate>
+</CertificateChain>
+<SignatureValue>kMWoh5eb2sVSzm6OV38MQ/NnXvYIzzyHu5wQv8OoENNykxSmPcHaSWs9Onn8my+F4s7sCG/NxgCu7ZuXKQFzE9fd8WDqaJQ/MXp2DRyqkobSgA+PEyz8gKV4qYUuz/1rRoU0YgPXtVO+ptbv/RqIbsOs2w7VKXHhhrQlMXU7/lc=</SignatureValue>
+</TizenLicense>
diff --git a/test/sample_contents/RO/FightGuiIF-1.0.0.signature_invalid.ro b/test/sample_contents/RO/FightGuiIF-1.0.0.signature_invalid.ro
new file mode 100644
index 0000000..55f30c8
--- /dev/null
+++ b/test/sample_contents/RO/FightGuiIF-1.0.0.signature_invalid.ro
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<TizenLicense>
+<LicenseInfo>
+ <version>2.0</version>
+ <uid>f4bc06a9fd3cc17a80fbc005b5f0e3392b9c121f401926113a18192aa3698b00d3e418075695e93c46f3a829759b44c51002ec661b601ec5414304cc5d3fea47</uid>
+</LicenseInfo>
+<ContentInfo>
+ <cid>FightGuiIF-1.0.0</cid>
+</ContentInfo>
+<KeyInfo>
+ <CipherValue>NFqUKMP0RD+Gbc/FeB8jzumbxEWjMEcetOCvlg/eqbQ=</CipherValue>
+</KeyInfo>
+<DeviceInfo>
+ <DUID>njkbucn1dogaw</DUID>
+</DeviceInfo>
+<CertificateChain>
+ <Certificate>MIIEXDCCA0SgAwIBAgIBRzANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTExMDIxMTAzMTAzMFoXDTMxMDIwNjAzMTAzMFowaDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxHjAcBgNVBAsTFU1lZGlhIFNvbHV0aW9uIENlbnRlcjEbMBkGA1UEAxMSRFJNKEFTVE9SRTItSU4tMDApMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhQisSmZqzucRFG8ckX4NtZgJSxdahP0OmKdRUoF3zxSrKXmiWj7fLRcj1puufn5TlikOVQmXwFPliqV90bUmOWHvc06Z8Sv2pdDas3foZ2pSDs+MZS1XTjhLkLTwkiNYFnzYepW2JueMF+EXZfWLKWCUK2sNvJux8dQcwhJIHZwIDAQABo4IBdzCCAXMwRgYIKwYBBQUHAQEEOjA4MDYGCCsGAQUFBzABhipodHRwOi8vcHViLm9zcHNlcnZlci5uZXQvc2VjdXJpdHkvc2NhL29jc3AwCQYDVR0TBAIwADCCAQ8GA1UdHwSCAQYwggECMIH/oHGgb4ZtbGRhcDovLzIxMC4xMTguNTcuMjk6Mzg5L0NOPWRwMSxPVT1NZWRpYSBTb2x1dGlvbiBDZW50ZXIsTz1TYW1zdW5nIEVsZWN0cm9uaWNzLEM9S1I/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdKKBiaSBhjCBgzEmMCQGA1UEAwwdU2Ftc3VuZyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxLjAsBgNVBAsMJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxHDAaBgNVBAoME1NhbXN1bmcgRWxlY3Ryb25pY3MxCzAJBgNVBAYTAktSMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQUFAAOCAQEAgX10I66EwTMdLNBiC6LRwFwDCaAbht6PsNeH0jvyph7d9gReNyJ0O15y+GFoFX3ta0K4xaf6qUcSg+8lRgkuMCxdMSqzN1e1ytmiLG/KQszXC2RtIEkSTe9DRh2u/Ozx5UwEL0ZO9MpTTlcti26MJ2dCbkfD2RHHqoQb5dJgUq2l8nAKVIWARjz3fdTdTbvqErTyUx7Oysch9nhu8OyymoLgoMI42kalgundQF6yYk+1XV34V72lM+z+9kak35pl9+j6XHA2S2HsyPN6JLzQfRxN05Kotyo5sHkNRX/fsTNe/xDOlDQccCf7uKZp9zwonBQB2XG6eZhI3hy7WLRb4Q==</Certificate>
+ <Certificate>MIIEFTCCAv2gAwIBAgIBADANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxKzApBgNVBAMTIlNhbXN1bmcgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDkxMTAyMDI1NDIwWhcNMjAxMDMwMDI1NDIwWjCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0bkji6Mggsv+hEUFd6FCLOUp0fXlqyGNzND/iD0KzeHfxiNkne55lpEpMQ8RR2Mk0oIMru8slnmlQe4G+Wi4ejuA+thpwtmcMHbiABk/1gb59agHEgiAWCYyGBtwTlNvjoC17pR7qTXp54LeDlinOVdqrr8KuDfxrD23IzkWoDFvTBxgh4Je86NMgG9CNoPcWgsFH2NSbmHlGMJGhQNyrzu9N8kT5RNdhZ3YA6y2Op1O2W61bCMoFaCxYuJBoF834umMX1QpMLdPyhDWvyRQF8eyrujk/lbxKFoUtoQdWo92wkH9fJzPbcrjzV08T0Zzv0ZMqI+cG1NUq4JGXJCztwIDAQABo4GMMIGJMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgH+MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUkjW5KAWZqeoa1Zc7sPtsrAhvbIUwHwYDVR0jBBgwFoAUdSvSt/cYuTKeXokzT+hjkv6fjVYwDQYJKoZIhvcNAQEFBQADggEBALoBA2T15qfVXYfaJaWeLNrM/68u7MeBX9zWfFLHIfjSxlJjyEGEJNEMPkNBS8XMXxG47+oRrTn9pHNVqkkA1g9TB7AJRSdiVhT0n5PfaUX73SBE2HzNOxB7dX6lUFbTtzjUNlJm40f4DBdkGEcmBMQZG8ffQbe50VS/e4e7DYX6bunxskf/9ROUcKwY43hFnP9S+RPE78QRsWkmfhxpNqXkJnQNodeNEJ3N05XmtNFjCdg+T67ldAHrZ6blYKC5J09p27T+Gp2WdOEDEKcgaOZQvgi6MC+mbxRlnIJKpAFM0y6TlrA/9leSX/aikqhcxiUf7mGKO0BfaCAbAQLkw5w=</Certificate>
+</CertificateChain>
+<SignatureValue>kkkoh5eb2sVSzm6OV38MQ/NnXvYIzzyHu5wQv8OoENNykxSmPcHaSWs9Onn8my+F4s7sCG/NxgCu7ZuXKQFzE9fd8WDqaJQ/MXp2DRyqkobSgA+PEyz8gKV4qYUuz/1rRoU0YgPXtVO+ptbv/RqIbsOs2w7VKXHhhrQlMXU7/lc=</SignatureValue>
+</TizenLicense>
diff --git a/test/sample_contents/RO/X5YVR2zmQZ.cert_chain_invalid.ro b/test/sample_contents/RO/X5YVR2zmQZ.cert_chain_invalid.ro
new file mode 100644
index 0000000..0e9202c
--- /dev/null
+++ b/test/sample_contents/RO/X5YVR2zmQZ.cert_chain_invalid.ro
@@ -0,0 +1,37 @@
+<o-ex:rights xmlns:o-ex="http://odrl.net/1.1/ODRL-EX" xmlns:o-dd="http://odrl.net/1.1/ODRL-DD" xmlns:oma-dd="http://www.openmobilealliance.com/oma-dd" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" o-ex:id="SAD-RO2.0">
+ <o-ex:context>
+ <o-dd:version>2.0</o-dd:version>
+ <o-dd:uid>6ae9897f613140cedfd99879a11ecbcad56b7128345d0eb0b3e16fc4c0932573bf63aad6bfcffe9f162826f840b6c2aa575fe8a8c0bdf1cf0ebbe1a1043812da</o-dd:uid>
+ </o-ex:context>
+ <o-ex:agreement>
+ <o-ex:asset>
+ <o-ex:context>
+ <o-dd:uid>X5YVR2zmQZ-1.0.0</o-dd:uid>
+ </o-ex:context>
+ <ds:KeyInfo>
+ <xenc:EncryptedKey>
+ <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#kw-aes128"/>
+ <xenc:CipherData>
+ <xenc:CipherValue>UU/MkzJVSP+PKmxu7tBfkWVZ98SiTUeFqfaIqGNw9CU=</xenc:CipherValue>
+ </xenc:CipherData>
+ </xenc:EncryptedKey>
+ </ds:KeyInfo>
+ </o-ex:asset>
+ <o-ex:permission>
+ <o-dd:execute>
+ <o-ex:constraint>
+ <o-dd:individual>
+ <o-ex:context>
+ <o-dd:uid>IMEI:354706050048713</o-dd:uid>
+ </o-ex:context>
+ </o-dd:individual>
+ </o-ex:constraint>
+ </o-dd:execute>
+ </o-ex:permission>
+ </o-ex:agreement>
+ <certificateChain>
+ <certificate>MIICiDCCAfGgAwIBAgIGAT3uVWhhMA0GCSqGSIb3DQEBBQUAMIGEMQswCQYDVQQGEwJLUjEOMAwGA1UECAwFU3V3b24xDjAMBgNVBAcMBVN1d29uMRYwFAYDVQQKDA1UaXplbiBUZXN0IENBMSAwHgYDVQQLDBdUaXplbiBEZXZlbG9wZXIgVGVzdCBDQTEbMBkGA1UEAwwSVGl6ZW4gRGV2ZWxvcGVyIENBMB4XDTEzMDQwOTEwMjY0N1oXDTQwMDgyNTEwMjY0NlowgYkxCzAJBgNVBAYTAktSMREwDwYDVQQIDAhLeXVuZy1naTEOMAwGA1UEBwwFU3V3b24xEDAOBgNVBAoMB1NhbXN1bmcxDDAKBgNVBAsMA1NQRzEnMCUGCSqGSIb3DQEJARYYc3VuZ2d1bi5qdW5nQHNhbXN1bmcuY29tMQ4wDAYDVQQDDAVGdEFwcDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAg43VXwzDa498f/+JiD38kDqiQ0Wx7/nEciwa2pktcna8KwSSUYIghExLZmQLBfudkxBpDeq+iEQzFm5QtSrH3KwJX6Da/PYTS3W7C4XdrbAWShPkSVyUp86P7u2Q+dwoAdPfqANm7DdTxQ4BUdtNtYcATQ9PHIu0Dk7OACBLb1kCAwEAATANBgkqhkiG9w0BAQUFAAOBgQCe9h4VRqMmU+7OH8BHJiIwnbdvfWnyGBjVQ4BrcybeTu6A2IgTibY4n6eelW2gFqxozI+fl5hW8wCRQNyDO2mef/WfopkJGbafpRv3eJfT2gKjJHRJEvaXutD3cPfvvOvzmMw0YijII3KhzIrbi3Fekg52nLkRZKHrqkQQvQfsOA==</certificate>
+ <certificate>MIICpzCCAhCgAwIBAgIJAKzDjmEF+1OXMA0GCSqGSIb3DQEBBQUAMIGTMQswCQYDVQQGEwJLUjEOMAwGA1UECAwFU3V3b24xDjAMBgNVBAcMBVN1d29uMRYwFAYDVQQKDA1UaXplbiBUZXN0IENBMSUwIwYDVQQLDBxUaXplbiBUZXN0IERldmVsb3BlciBSb290IENBMSUwIwYDVQQDDBxUaXplbiBUZXN0IERldmVsb3BlciBSb290IENBMB4XDTEyMTAyOTEzMDEyMloXDTIyMTAyNzEzMDEyMlowgYQxCzAJBgNVBAYTAktSMQ4wDAYDVQQIDAVTdXdvbjEOMAwGA1UEBwwFU3V3b24xFjAUBgNVBAoMDVRpemVuIFRlc3QgQ0ExIDAeBgNVBAsMF1RpemVuIERldmVsb3BlciBUZXN0IENBMRswGQYDVQQDDBJUaXplbiBEZXZlbG9wZXIgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMyG0DSTHBgalQo1seDKxpCU61gji+QQlxQkPQOvBrmuF6Z90zFCprTtg2sRjTLCNoRd75+VCCHuKGcrD27t7hwAekusPrpzdsq5QoBMvNjGDM22lC45PJ4d86DEDY4erxeJ5aSQxqbfXK4pKe9NwxdkKuA8dTYZM1UcmhXs7YALAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEACbr/OPNMJ+Ejrxfm/YjCiRPpjJLnwXS2IDtitbxot6bEdZkZvOFXOC0Ca4GT+jtvOcSlU7tM3Mdd1MrKe1kkoVd1vhCV8V4CK3/DPj8aN3rxfMfQitA6XMDcxzhsyMWz56OdifX50dvS/G/ad+kGhNhOOEKSE8zUyEDCGwqkfXk=</certificate>
+ </certificateChain>
+ <signature>xkl49MqlUt2j6T0oqhy0loYOhFEaj2bdmYlswgIV3RwIYXRteu36vREItnvzta0KctjV4goj7/x4IhZ7nLeNBZfHRDUmtCgMAoWqIdo0FMIduF4PaIBgtlqGfTrMe5EsOTi/PKTMy4LbIUwvdJRldhR2iXtWyZEDAG6IYPvRSIE=</signature>
+</o-ex:rights>
diff --git a/test/sample_contents/RO/X5YVR2zmQZ.ro b/test/sample_contents/RO/X5YVR2zmQZ.ro
new file mode 100644
index 0000000..4403afb
--- /dev/null
+++ b/test/sample_contents/RO/X5YVR2zmQZ.ro
@@ -0,0 +1,37 @@
+<o-ex:rights xmlns:o-ex="http://odrl.net/1.1/ODRL-EX" xmlns:o-dd="http://odrl.net/1.1/ODRL-DD" xmlns:oma-dd="http://www.openmobilealliance.com/oma-dd" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" o-ex:id="SAD-RO2.0">
+ <o-ex:context>
+ <o-dd:version>2.0</o-dd:version>
+ <o-dd:uid>6ae9897f613140cedfd99879a11ecbcad56b7128345d0eb0b3e16fc4c0932573bf63aad6bfcffe9f162826f840b6c2aa575fe8a8c0bdf1cf0ebbe1a1043812da</o-dd:uid>
+ </o-ex:context>
+ <o-ex:agreement>
+ <o-ex:asset>
+ <o-ex:context>
+ <o-dd:uid>X5YVR2zmQZ-1.0.0</o-dd:uid>
+ </o-ex:context>
+ <ds:KeyInfo>
+ <xenc:EncryptedKey>
+ <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#kw-aes128"/>
+ <xenc:CipherData>
+ <xenc:CipherValue>UU/MkzJVSP+PKmxu7tBfkWVZ98SiTUeFqfaIqGNw9CU=</xenc:CipherValue>
+ </xenc:CipherData>
+ </xenc:EncryptedKey>
+ </ds:KeyInfo>
+ </o-ex:asset>
+ <o-ex:permission>
+ <o-dd:execute>
+ <o-ex:constraint>
+ <o-dd:individual>
+ <o-ex:context>
+ <o-dd:uid>IMEI:354706050048713</o-dd:uid>
+ </o-ex:context>
+ </o-dd:individual>
+ </o-ex:constraint>
+ </o-dd:execute>
+ </o-ex:permission>
+ </o-ex:agreement>
+ <certificateChain>
+ <certificate>MIIEXDCCA0SgAwIBAgIBRzANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTExMDIxMTAzMTAzMFoXDTMxMDIwNjAzMTAzMFowaDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxHjAcBgNVBAsTFU1lZGlhIFNvbHV0aW9uIENlbnRlcjEbMBkGA1UEAxMSRFJNKEFTVE9SRTItSU4tMDApMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhQisSmZqzucRFG8ckX4NtZgJSxdahP0OmKdRUoF3zxSrKXmiWj7fLRcj1puufn5TlikOVQmXwFPliqV90bUmOWHvc06Z8Sv2pdDas3foZ2pSDs+MZS1XTjhLkLTwkiNYFnzYepW2JueMF+EXZfWLKWCUK2sNvJux8dQcwhJIHZwIDAQABo4IBdzCCAXMwRgYIKwYBBQUHAQEEOjA4MDYGCCsGAQUFBzABhipodHRwOi8vcHViLm9zcHNlcnZlci5uZXQvc2VjdXJpdHkvc2NhL29jc3AwCQYDVR0TBAIwADCCAQ8GA1UdHwSCAQYwggECMIH/oHGgb4ZtbGRhcDovLzIxMC4xMTguNTcuMjk6Mzg5L0NOPWRwMSxPVT1NZWRpYSBTb2x1dGlvbiBDZW50ZXIsTz1TYW1zdW5nIEVsZWN0cm9uaWNzLEM9S1I/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdKKBiaSBhjCBgzEmMCQGA1UEAwwdU2Ftc3VuZyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxLjAsBgNVBAsMJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxHDAaBgNVBAoME1NhbXN1bmcgRWxlY3Ryb25pY3MxCzAJBgNVBAYTAktSMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQUFAAOCAQEAgX10I66EwTMdLNBiC6LRwFwDCaAbht6PsNeH0jvyph7d9gReNyJ0O15y+GFoFX3ta0K4xaf6qUcSg+8lRgkuMCxdMSqzN1e1ytmiLG/KQszXC2RtIEkSTe9DRh2u/Ozx5UwEL0ZO9MpTTlcti26MJ2dCbkfD2RHHqoQb5dJgUq2l8nAKVIWARjz3fdTdTbvqErTyUx7Oysch9nhu8OyymoLgoMI42kalgundQF6yYk+1XV34V72lM+z+9kak35pl9+j6XHA2S2HsyPN6JLzQfRxN05Kotyo5sHkNRX/fsTNe/xDOlDQccCf7uKZp9zwonBQB2XG6eZhI3hy7WLRb4Q==</certificate>
+ <certificate>MIIEFTCCAv2gAwIBAgIBADANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxKzApBgNVBAMTIlNhbXN1bmcgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDkxMTAyMDI1NDIwWhcNMjAxMDMwMDI1NDIwWjCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0bkji6Mggsv+hEUFd6FCLOUp0fXlqyGNzND/iD0KzeHfxiNkne55lpEpMQ8RR2Mk0oIMru8slnmlQe4G+Wi4ejuA+thpwtmcMHbiABk/1gb59agHEgiAWCYyGBtwTlNvjoC17pR7qTXp54LeDlinOVdqrr8KuDfxrD23IzkWoDFvTBxgh4Je86NMgG9CNoPcWgsFH2NSbmHlGMJGhQNyrzu9N8kT5RNdhZ3YA6y2Op1O2W61bCMoFaCxYuJBoF834umMX1QpMLdPyhDWvyRQF8eyrujk/lbxKFoUtoQdWo92wkH9fJzPbcrjzV08T0Zzv0ZMqI+cG1NUq4JGXJCztwIDAQABo4GMMIGJMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgH+MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUkjW5KAWZqeoa1Zc7sPtsrAhvbIUwHwYDVR0jBBgwFoAUdSvSt/cYuTKeXokzT+hjkv6fjVYwDQYJKoZIhvcNAQEFBQADggEBALoBA2T15qfVXYfaJaWeLNrM/68u7MeBX9zWfFLHIfjSxlJjyEGEJNEMPkNBS8XMXxG47+oRrTn9pHNVqkkA1g9TB7AJRSdiVhT0n5PfaUX73SBE2HzNOxB7dX6lUFbTtzjUNlJm40f4DBdkGEcmBMQZG8ffQbe50VS/e4e7DYX6bunxskf/9ROUcKwY43hFnP9S+RPE78QRsWkmfhxpNqXkJnQNodeNEJ3N05XmtNFjCdg+T67ldAHrZ6blYKC5J09p27T+Gp2WdOEDEKcgaOZQvgi6MC+mbxRlnIJKpAFM0y6TlrA/9leSX/aikqhcxiUf7mGKO0BfaCAbAQLkw5w=</certificate>
+ </certificateChain>
+ <signature>xkl49MqlUt2j6T0oqhy0loYOhFEaj2bdmYlswgIV3RwIYXRteu36vREItnvzta0KctjV4goj7/x4IhZ7nLeNBZfHRDUmtCgMAoWqIdo0FMIduF4PaIBgtlqGfTrMe5EsOTi/PKTMy4LbIUwvdJRldhR2iXtWyZEDAG6IYPvRSIE=</signature>
+</o-ex:rights>
diff --git a/test/sample_contents/RO/X5YVR2zmQZ.signature_invalid.ro b/test/sample_contents/RO/X5YVR2zmQZ.signature_invalid.ro
new file mode 100644
index 0000000..cb082eb
--- /dev/null
+++ b/test/sample_contents/RO/X5YVR2zmQZ.signature_invalid.ro
@@ -0,0 +1,37 @@
+<o-ex:rights xmlns:o-ex="http://odrl.net/1.1/ODRL-EX" xmlns:o-dd="http://odrl.net/1.1/ODRL-DD" xmlns:oma-dd="http://www.openmobilealliance.com/oma-dd" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" o-ex:id="SAD-RO2.0">
+ <o-ex:context>
+ <o-dd:version>2.0</o-dd:version>
+ <o-dd:uid>6ae9897f613140cedfd99879a11ecbcad56b7128345d0eb0b3e16fc4c0932573bf63aad6bfcffe9f162826f840b6c2aa575fe8a8c0bdf1cf0ebbe1a1043812da</o-dd:uid>
+ </o-ex:context>
+ <o-ex:agreement>
+ <o-ex:asset>
+ <o-ex:context>
+ <o-dd:uid>X5YVR2zmQZ-1.0.0</o-dd:uid>
+ </o-ex:context>
+ <ds:KeyInfo>
+ <xenc:EncryptedKey>
+ <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#kw-aes128"/>
+ <xenc:CipherData>
+ <xenc:CipherValue>UU/MkzJVSP+PKmxu7tBfkWVZ98SiTUeFqfaIqGNw9CU=</xenc:CipherValue>
+ </xenc:CipherData>
+ </xenc:EncryptedKey>
+ </ds:KeyInfo>
+ </o-ex:asset>
+ <o-ex:permission>
+ <o-dd:execute>
+ <o-ex:constraint>
+ <o-dd:individual>
+ <o-ex:context>
+ <o-dd:uid>IMEI:354706050048713</o-dd:uid>
+ </o-ex:context>
+ </o-dd:individual>
+ </o-ex:constraint>
+ </o-dd:execute>
+ </o-ex:permission>
+ </o-ex:agreement>
+ <certificateChain>
+ <certificate>MIIEXDCCA0SgAwIBAgIBRzANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTExMDIxMTAzMTAzMFoXDTMxMDIwNjAzMTAzMFowaDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxHjAcBgNVBAsTFU1lZGlhIFNvbHV0aW9uIENlbnRlcjEbMBkGA1UEAxMSRFJNKEFTVE9SRTItSU4tMDApMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhQisSmZqzucRFG8ckX4NtZgJSxdahP0OmKdRUoF3zxSrKXmiWj7fLRcj1puufn5TlikOVQmXwFPliqV90bUmOWHvc06Z8Sv2pdDas3foZ2pSDs+MZS1XTjhLkLTwkiNYFnzYepW2JueMF+EXZfWLKWCUK2sNvJux8dQcwhJIHZwIDAQABo4IBdzCCAXMwRgYIKwYBBQUHAQEEOjA4MDYGCCsGAQUFBzABhipodHRwOi8vcHViLm9zcHNlcnZlci5uZXQvc2VjdXJpdHkvc2NhL29jc3AwCQYDVR0TBAIwADCCAQ8GA1UdHwSCAQYwggECMIH/oHGgb4ZtbGRhcDovLzIxMC4xMTguNTcuMjk6Mzg5L0NOPWRwMSxPVT1NZWRpYSBTb2x1dGlvbiBDZW50ZXIsTz1TYW1zdW5nIEVsZWN0cm9uaWNzLEM9S1I/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdKKBiaSBhjCBgzEmMCQGA1UEAwwdU2Ftc3VuZyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxLjAsBgNVBAsMJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxHDAaBgNVBAoME1NhbXN1bmcgRWxlY3Ryb25pY3MxCzAJBgNVBAYTAktSMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQUFAAOCAQEAgX10I66EwTMdLNBiC6LRwFwDCaAbht6PsNeH0jvyph7d9gReNyJ0O15y+GFoFX3ta0K4xaf6qUcSg+8lRgkuMCxdMSqzN1e1ytmiLG/KQszXC2RtIEkSTe9DRh2u/Ozx5UwEL0ZO9MpTTlcti26MJ2dCbkfD2RHHqoQb5dJgUq2l8nAKVIWARjz3fdTdTbvqErTyUx7Oysch9nhu8OyymoLgoMI42kalgundQF6yYk+1XV34V72lM+z+9kak35pl9+j6XHA2S2HsyPN6JLzQfRxN05Kotyo5sHkNRX/fsTNe/xDOlDQccCf7uKZp9zwonBQB2XG6eZhI3hy7WLRb4Q==</certificate>
+ <certificate>MIIEFTCCAv2gAwIBAgIBADANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxKzApBgNVBAMTIlNhbXN1bmcgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDkxMTAyMDI1NDIwWhcNMjAxMDMwMDI1NDIwWjCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0bkji6Mggsv+hEUFd6FCLOUp0fXlqyGNzND/iD0KzeHfxiNkne55lpEpMQ8RR2Mk0oIMru8slnmlQe4G+Wi4ejuA+thpwtmcMHbiABk/1gb59agHEgiAWCYyGBtwTlNvjoC17pR7qTXp54LeDlinOVdqrr8KuDfxrD23IzkWoDFvTBxgh4Je86NMgG9CNoPcWgsFH2NSbmHlGMJGhQNyrzu9N8kT5RNdhZ3YA6y2Op1O2W61bCMoFaCxYuJBoF834umMX1QpMLdPyhDWvyRQF8eyrujk/lbxKFoUtoQdWo92wkH9fJzPbcrjzV08T0Zzv0ZMqI+cG1NUq4JGXJCztwIDAQABo4GMMIGJMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgH+MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUkjW5KAWZqeoa1Zc7sPtsrAhvbIUwHwYDVR0jBBgwFoAUdSvSt/cYuTKeXokzT+hjkv6fjVYwDQYJKoZIhvcNAQEFBQADggEBALoBA2T15qfVXYfaJaWeLNrM/68u7MeBX9zWfFLHIfjSxlJjyEGEJNEMPkNBS8XMXxG47+oRrTn9pHNVqkkA1g9TB7AJRSdiVhT0n5PfaUX73SBE2HzNOxB7dX6lUFbTtzjUNlJm40f4DBdkGEcmBMQZG8ffQbe50VS/e4e7DYX6bunxskf/9ROUcKwY43hFnP9S+RPE78QRsWkmfhxpNqXkJnQNodeNEJ3N05XmtNFjCdg+T67ldAHrZ6blYKC5J09p27T+Gp2WdOEDEKcgaOZQvgi6MC+mbxRlnIJKpAFM0y6TlrA/9leSX/aikqhcxiUf7mGKO0BfaCAbAQLkw5w=</certificate>
+ </certificateChain>
+ <signature>xkl49MqlUt2j6T0oqhy0loYOhFEaj2bdmYlswgIV3RwIYXRteu36vREItnvzta0KctjV4goj7/x4IhZ7nLeNBZfHRDUmtCgMAoWqIdo0FMIduF4PaIBgtlqGfTrMe5EsOTi/PKTMy4LbIUwvdJRldhR2iXtWyZEDAG6IYPvRSkk=</signature>
+</o-ex:rights>
diff --git a/test/sample_contents/RO/ZdAXXZx2HZ.cert_invalid.ro b/test/sample_contents/RO/ZdAXXZx2HZ.cert_invalid.ro
new file mode 100644
index 0000000..6139b4c
--- /dev/null
+++ b/test/sample_contents/RO/ZdAXXZx2HZ.cert_invalid.ro
@@ -0,0 +1,37 @@
+<o-ex:rights xmlns:o-ex="http://odrl.net/1.1/ODRL-EX" xmlns:o-dd="http://odrl.net/1.1/ODRL-DD" xmlns:oma-dd="http://www.openmobilealliance.com/oma-dd" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" o-ex:id="SAD-RO2.0">
+ <o-ex:context>
+ <o-dd:version>2.0</o-dd:version>
+ <o-dd:uid>bd3b8434ce42f5ed2396171427008b509200da82fb04d5f31a3d58543cd62c955f723a8f1ddf9f9e902aa0293c4e87c41e6f74ef0fee67446752543b1e9f27e9</o-dd:uid>
+ </o-ex:context>
+ <o-ex:agreement>
+ <o-ex:asset>
+ <o-ex:context>
+ <o-dd:uid>ZdAXXZx2HZ-2.0.0</o-dd:uid>
+ </o-ex:context>
+ <ds:KeyInfo>
+ <xenc:EncryptedKey>
+ <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#kw-aes128"/>
+ <xenc:CipherData>
+ <xenc:CipherValue>AjXkz8x9SdCadHrdfLCXLaEc0IvHCUlbvsr1sY3p3cw=</xenc:CipherValue>
+ </xenc:CipherData>
+ </xenc:EncryptedKey>
+ </ds:KeyInfo>
+ </o-ex:asset>
+ <o-ex:permission>
+ <o-dd:execute>
+ <o-ex:constraint>
+ <o-dd:individual>
+ <o-ex:context>
+ <o-dd:uid>IMEI:354706050048713</o-dd:uid>
+ </o-ex:context>
+ </o-dd:individual>
+ </o-ex:constraint>
+ </o-dd:execute>
+ </o-ex:permission>
+ </o-ex:agreement>
+ <certificateChain>
+ <certificate>MIIEXDCCA0SgAwIBAgIBRzANBgkqhkiG9w0BQUFADCBgzELAkGA1UEBhMS1IxHDAaBgNBAoTE1NhbXNbmcgRWxlY3Rb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTExMDIxMTAzMTAzMFoXDTMxMDIwNjAzMTAzMFowaDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxHjAcBgNVBAsTFU1lZGlhIFNvbHV0aW9uIENlbnRlcjEbMBkGA1UEAxMSRFJNKEFTVE9SRTItSU4tMDApMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhQisSmZqzucRFG8ckX4NtZgJSxdahP0OmKdRUoF3zxSrKXmiWj7fLRcj1puufn5TlikOVQmXwFPliqV90bUmOWHvc06Z8Sv2pdDas3foZ2pSDs+MZS1XTjhLkLTwkiNYFnzYepW2JueMF+EXZfWLKWCUK2sNvJux8dQcwhJIHZwIDAQABo4IBdzCCAXMwRgYIKwYBBQUHAQEEOjA4MDYGCCsGAQUFBzABhipodHRwOi8vcHViLm9zcHNlcnZlci5uZXQvc2VjdXJpdHkvc2NhL29jc3AwCQYDVR0TBAIwADCCAQ8GA1UdHwSCAQYwggECMIH/oHGgb4ZtbGRhcDovLzIxMC4xMTguNTcuMjk6Mzg5L0NOPWRwMSxPVT1NZWRpYSBTb2x1dGlvbiBDZW50ZXIsTz1TYW1zdW5nIEVsZWN0cm9uaWNzLEM9S1I/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdKKBiaSBhjCBgzEmMCQGA1UEAwwdU2Ftc3VuZyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxLjAsBgNVBAsMJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxHDAaBgNVBAoME1NhbXN1bmcgRWxlY3Ryb25pY3MxCzAJBgNVBAYTAktSMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQUFAAOCAQEAgX10I66EwTMdLNBiC6LRwFwDCaAbht6PsNeH0jvyph7d9gReNyJ0O15y+GFoFX3ta0K4xaf6qUcSg+8lRgkuMCxdMSqzN1e1ytmiLG/KQszXC2RtIEkSTe9DRh2u/Ozx5UwEL0ZO9MpTTlcti26MJ2dCbkfD2RHHqoQb5dJgUq2l8nAKVIWARjz3fdTdTbvqErTyUx7Oysch9nhu8OyymoLgoMI42kalgundQF6yYk+1XV34V72lM+z+9kak35pl9+j6XHA2S2HsyPN6JLzQfRxN05Kotyo5sHkNRX/fsTNe/xDOlDQccCf7uKZp9zwonBQB2XG6eZhI3hy7WLRb4Q==</certificate>
+ <certificate>MIIEFTCCAv2gAwIBAgIBADANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWl3Ryb25pY3MxjAsBgNVBAsTJVNbXN1bmcgQ2VydGlaWNhdGUgQXV0aGyaXR5IENlbnRyWwxKzApBgNVBAMTIlNhbXN1bmcgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDkxMTAyMDI1NDIwWhcNMjAxMDMwMDI1NDIwWjCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0bkji6Mggsv+hEUFd6FCLOUp0fXlqyGNzND/iD0KzeHfxiNkne55lpEpMQ8RR2Mk0oIMru8slnmlQe4G+Wi4ejuA+thpwtmcMHbiABk/1gb59agHEgiAWCYyGBtwTlNvjoC17pR7qTXp54LeDlinOVdqrr8KuDfxrD23IzkWoDFvTBxgh4Je86NMgG9CNoPcWgsFH2NSbmHlGMJGhQNyrzu9N8kT5RNdhZ3YA6y2Op1O2W61bCMoFaCxYuJBoF834umMX1QpMLdPyhDWvyRQF8eyrujk/lbxKFoUtoQdWo92wkH9fJzPbcrjzV08T0Zzv0ZMqI+cG1NUq4JGXJCztwIDAQABo4GMMIGJMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgH+MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUkjW5KAWZqeoa1Zc7sPtsrAhvbIUwHwYDVR0jBBgwFoAUdSvSt/cYuTKeXokzT+hjkv6fjVYwDQYJKoZIhvcNAQEFBQADggEBALoBA2T15qfVXYfaJaWeLNrM/68u7MeBX9zWfFLHIfjSxlJjyEGEJNEMPkNBS8XMXxG47+oRrTn9pHNVqkkA1g9TB7AJRSdiVhT0n5PfaUX73SBE2HzNOxB7dX6lUFbTtzjUNlJm40f4DBdkGEcmBMQZG8ffQbe50VS/e4e7DYX6bunxskf/9ROUcKwY43hFnP9S+RPE78QRsWkmfhxpNqXkJnQNodeNEJ3N05XmtNFjCdg+T67ldAHrZ6blYKC5J09p27T+Gp2WdOEDEKcgaOZQvgi6MC+mbxRlnIJKpAFM0y6TlrA/9leSX/aikqhcxiUf7mGKO0BfaCAbAQLkw5w=</certificate>
+ </certificateChain>
+ <signature>wK9PeRx5aAXw12nl76Z/3cZ8qRptNQTFKY1KTXv2Vfei0gfmBKgGcLhPrb8uGcIBQUL4KYQsCjCS7MhZ+sWuCYMkTXv9Vi/pwuRuBFxzC7fhWs8YDzGQKilj+iYNpRcJdAJBsIanGFm+xYF2sRj5c/vew+NWsC4pUKHAEsdkkdg=</signature>
+</o-ex:rights>
diff --git a/test/sample_contents/RO/ZdAXXZx2HZ.ro b/test/sample_contents/RO/ZdAXXZx2HZ.ro
new file mode 100644
index 0000000..78f17d7
--- /dev/null
+++ b/test/sample_contents/RO/ZdAXXZx2HZ.ro
@@ -0,0 +1,37 @@
+<o-ex:rights xmlns:o-ex="http://odrl.net/1.1/ODRL-EX" xmlns:o-dd="http://odrl.net/1.1/ODRL-DD" xmlns:oma-dd="http://www.openmobilealliance.com/oma-dd" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" o-ex:id="SAD-RO2.0">
+ <o-ex:context>
+ <o-dd:version>2.0</o-dd:version>
+ <o-dd:uid>bd3b8434ce42f5ed2396171427008b509200da82fb04d5f31a3d58543cd62c955f723a8f1ddf9f9e902aa0293c4e87c41e6f74ef0fee67446752543b1e9f27e9</o-dd:uid>
+ </o-ex:context>
+ <o-ex:agreement>
+ <o-ex:asset>
+ <o-ex:context>
+ <o-dd:uid>ZdAXXZx2HZ-2.0.0</o-dd:uid>
+ </o-ex:context>
+ <ds:KeyInfo>
+ <xenc:EncryptedKey>
+ <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#kw-aes128"/>
+ <xenc:CipherData>
+ <xenc:CipherValue>AjXkz8x9SdCadHrdfLCXLaEc0IvHCUlbvsr1sY3p3cw=</xenc:CipherValue>
+ </xenc:CipherData>
+ </xenc:EncryptedKey>
+ </ds:KeyInfo>
+ </o-ex:asset>
+ <o-ex:permission>
+ <o-dd:execute>
+ <o-ex:constraint>
+ <o-dd:individual>
+ <o-ex:context>
+ <o-dd:uid>IMEI:354706050048713</o-dd:uid>
+ </o-ex:context>
+ </o-dd:individual>
+ </o-ex:constraint>
+ </o-dd:execute>
+ </o-ex:permission>
+ </o-ex:agreement>
+ <certificateChain>
+ <certificate>MIIEXDCCA0SgAwIBAgIBRzANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTExMDIxMTAzMTAzMFoXDTMxMDIwNjAzMTAzMFowaDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxHjAcBgNVBAsTFU1lZGlhIFNvbHV0aW9uIENlbnRlcjEbMBkGA1UEAxMSRFJNKEFTVE9SRTItSU4tMDApMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhQisSmZqzucRFG8ckX4NtZgJSxdahP0OmKdRUoF3zxSrKXmiWj7fLRcj1puufn5TlikOVQmXwFPliqV90bUmOWHvc06Z8Sv2pdDas3foZ2pSDs+MZS1XTjhLkLTwkiNYFnzYepW2JueMF+EXZfWLKWCUK2sNvJux8dQcwhJIHZwIDAQABo4IBdzCCAXMwRgYIKwYBBQUHAQEEOjA4MDYGCCsGAQUFBzABhipodHRwOi8vcHViLm9zcHNlcnZlci5uZXQvc2VjdXJpdHkvc2NhL29jc3AwCQYDVR0TBAIwADCCAQ8GA1UdHwSCAQYwggECMIH/oHGgb4ZtbGRhcDovLzIxMC4xMTguNTcuMjk6Mzg5L0NOPWRwMSxPVT1NZWRpYSBTb2x1dGlvbiBDZW50ZXIsTz1TYW1zdW5nIEVsZWN0cm9uaWNzLEM9S1I/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdKKBiaSBhjCBgzEmMCQGA1UEAwwdU2Ftc3VuZyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxLjAsBgNVBAsMJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxHDAaBgNVBAoME1NhbXN1bmcgRWxlY3Ryb25pY3MxCzAJBgNVBAYTAktSMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQUFAAOCAQEAgX10I66EwTMdLNBiC6LRwFwDCaAbht6PsNeH0jvyph7d9gReNyJ0O15y+GFoFX3ta0K4xaf6qUcSg+8lRgkuMCxdMSqzN1e1ytmiLG/KQszXC2RtIEkSTe9DRh2u/Ozx5UwEL0ZO9MpTTlcti26MJ2dCbkfD2RHHqoQb5dJgUq2l8nAKVIWARjz3fdTdTbvqErTyUx7Oysch9nhu8OyymoLgoMI42kalgundQF6yYk+1XV34V72lM+z+9kak35pl9+j6XHA2S2HsyPN6JLzQfRxN05Kotyo5sHkNRX/fsTNe/xDOlDQccCf7uKZp9zwonBQB2XG6eZhI3hy7WLRb4Q==</certificate>
+ <certificate>MIIEFTCCAv2gAwIBAgIBADANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxKzApBgNVBAMTIlNhbXN1bmcgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDkxMTAyMDI1NDIwWhcNMjAxMDMwMDI1NDIwWjCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0bkji6Mggsv+hEUFd6FCLOUp0fXlqyGNzND/iD0KzeHfxiNkne55lpEpMQ8RR2Mk0oIMru8slnmlQe4G+Wi4ejuA+thpwtmcMHbiABk/1gb59agHEgiAWCYyGBtwTlNvjoC17pR7qTXp54LeDlinOVdqrr8KuDfxrD23IzkWoDFvTBxgh4Je86NMgG9CNoPcWgsFH2NSbmHlGMJGhQNyrzu9N8kT5RNdhZ3YA6y2Op1O2W61bCMoFaCxYuJBoF834umMX1QpMLdPyhDWvyRQF8eyrujk/lbxKFoUtoQdWo92wkH9fJzPbcrjzV08T0Zzv0ZMqI+cG1NUq4JGXJCztwIDAQABo4GMMIGJMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgH+MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUkjW5KAWZqeoa1Zc7sPtsrAhvbIUwHwYDVR0jBBgwFoAUdSvSt/cYuTKeXokzT+hjkv6fjVYwDQYJKoZIhvcNAQEFBQADggEBALoBA2T15qfVXYfaJaWeLNrM/68u7MeBX9zWfFLHIfjSxlJjyEGEJNEMPkNBS8XMXxG47+oRrTn9pHNVqkkA1g9TB7AJRSdiVhT0n5PfaUX73SBE2HzNOxB7dX6lUFbTtzjUNlJm40f4DBdkGEcmBMQZG8ffQbe50VS/e4e7DYX6bunxskf/9ROUcKwY43hFnP9S+RPE78QRsWkmfhxpNqXkJnQNodeNEJ3N05XmtNFjCdg+T67ldAHrZ6blYKC5J09p27T+Gp2WdOEDEKcgaOZQvgi6MC+mbxRlnIJKpAFM0y6TlrA/9leSX/aikqhcxiUf7mGKO0BfaCAbAQLkw5w=</certificate>
+ </certificateChain>
+ <signature>wK9PeRx5aAXw12nl76Z/3cZ8qRptNQTFKY1KTXv2Vfei0gfmBKgGcLhPrb8uGcIBQUL4KYQsCjCS7MhZ+sWuCYMkTXv9Vi/pwuRuBFxzC7fhWs8YDzGQKilj+iYNpRcJdAJBsIanGFm+xYF2sRj5c/vew+NWsC4pUKHAEsdkkdg=</signature>
+</o-ex:rights>
diff --git a/test/sample_contents/RO/ZdAXXZx2HZ.signature_invalid.ro b/test/sample_contents/RO/ZdAXXZx2HZ.signature_invalid.ro
new file mode 100644
index 0000000..0591b23
--- /dev/null
+++ b/test/sample_contents/RO/ZdAXXZx2HZ.signature_invalid.ro
@@ -0,0 +1,37 @@
+<o-ex:rights xmlns:o-ex="http://odrl.net/1.1/ODRL-EX" xmlns:o-dd="http://odrl.net/1.1/ODRL-DD" xmlns:oma-dd="http://www.openmobilealliance.com/oma-dd" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" o-ex:id="SAD-RO2.0">
+ <o-ex:context>
+ <o-dd:version>2.0</o-dd:version>
+ <o-dd:uid>bd3b8434ce42f5ed2396171427008b509200da82fb04d5f31a3d58543cd62c955f723a8f1ddf9f9e902aa0293c4e87c41e6f74ef0fee67446752543b1e9f27e9</o-dd:uid>
+ </o-ex:context>
+ <o-ex:agreement>
+ <o-ex:asset>
+ <o-ex:context>
+ <o-dd:uid>ZdAXXZx2HZ-2.0.0</o-dd:uid>
+ </o-ex:context>
+ <ds:KeyInfo>
+ <xenc:EncryptedKey>
+ <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#kw-aes128"/>
+ <xenc:CipherData>
+ <xenc:CipherValue>AjXkz8x9SdCadHrdfLCXLaEc0IvHCUlbvsr1sY3p3cw=</xenc:CipherValue>
+ </xenc:CipherData>
+ </xenc:EncryptedKey>
+ </ds:KeyInfo>
+ </o-ex:asset>
+ <o-ex:permission>
+ <o-dd:execute>
+ <o-ex:constraint>
+ <o-dd:individual>
+ <o-ex:context>
+ <o-dd:uid>IMEI:354706050048713</o-dd:uid>
+ </o-ex:context>
+ </o-dd:individual>
+ </o-ex:constraint>
+ </o-dd:execute>
+ </o-ex:permission>
+ </o-ex:agreement>
+ <certificateChain>
+ <certificate>MIIEXDCCA0SgAwIBAgIBRzANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTExMDIxMTAzMTAzMFoXDTMxMDIwNjAzMTAzMFowaDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxHjAcBgNVBAsTFU1lZGlhIFNvbHV0aW9uIENlbnRlcjEbMBkGA1UEAxMSRFJNKEFTVE9SRTItSU4tMDApMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhQisSmZqzucRFG8ckX4NtZgJSxdahP0OmKdRUoF3zxSrKXmiWj7fLRcj1puufn5TlikOVQmXwFPliqV90bUmOWHvc06Z8Sv2pdDas3foZ2pSDs+MZS1XTjhLkLTwkiNYFnzYepW2JueMF+EXZfWLKWCUK2sNvJux8dQcwhJIHZwIDAQABo4IBdzCCAXMwRgYIKwYBBQUHAQEEOjA4MDYGCCsGAQUFBzABhipodHRwOi8vcHViLm9zcHNlcnZlci5uZXQvc2VjdXJpdHkvc2NhL29jc3AwCQYDVR0TBAIwADCCAQ8GA1UdHwSCAQYwggECMIH/oHGgb4ZtbGRhcDovLzIxMC4xMTguNTcuMjk6Mzg5L0NOPWRwMSxPVT1NZWRpYSBTb2x1dGlvbiBDZW50ZXIsTz1TYW1zdW5nIEVsZWN0cm9uaWNzLEM9S1I/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdKKBiaSBhjCBgzEmMCQGA1UEAwwdU2Ftc3VuZyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxLjAsBgNVBAsMJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxHDAaBgNVBAoME1NhbXN1bmcgRWxlY3Ryb25pY3MxCzAJBgNVBAYTAktSMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQUFAAOCAQEAgX10I66EwTMdLNBiC6LRwFwDCaAbht6PsNeH0jvyph7d9gReNyJ0O15y+GFoFX3ta0K4xaf6qUcSg+8lRgkuMCxdMSqzN1e1ytmiLG/KQszXC2RtIEkSTe9DRh2u/Ozx5UwEL0ZO9MpTTlcti26MJ2dCbkfD2RHHqoQb5dJgUq2l8nAKVIWARjz3fdTdTbvqErTyUx7Oysch9nhu8OyymoLgoMI42kalgundQF6yYk+1XV34V72lM+z+9kak35pl9+j6XHA2S2HsyPN6JLzQfRxN05Kotyo5sHkNRX/fsTNe/xDOlDQccCf7uKZp9zwonBQB2XG6eZhI3hy7WLRb4Q==</certificate>
+ <certificate>MIIEFTCCAv2gAwIBAgIBADANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxKzApBgNVBAMTIlNhbXN1bmcgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDkxMTAyMDI1NDIwWhcNMjAxMDMwMDI1NDIwWjCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0bkji6Mggsv+hEUFd6FCLOUp0fXlqyGNzND/iD0KzeHfxiNkne55lpEpMQ8RR2Mk0oIMru8slnmlQe4G+Wi4ejuA+thpwtmcMHbiABk/1gb59agHEgiAWCYyGBtwTlNvjoC17pR7qTXp54LeDlinOVdqrr8KuDfxrD23IzkWoDFvTBxgh4Je86NMgG9CNoPcWgsFH2NSbmHlGMJGhQNyrzu9N8kT5RNdhZ3YA6y2Op1O2W61bCMoFaCxYuJBoF834umMX1QpMLdPyhDWvyRQF8eyrujk/lbxKFoUtoQdWo92wkH9fJzPbcrjzV08T0Zzv0ZMqI+cG1NUq4JGXJCztwIDAQABo4GMMIGJMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgH+MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUkjW5KAWZqeoa1Zc7sPtsrAhvbIUwHwYDVR0jBBgwFoAUdSvSt/cYuTKeXokzT+hjkv6fjVYwDQYJKoZIhvcNAQEFBQADggEBALoBA2T15qfVXYfaJaWeLNrM/68u7MeBX9zWfFLHIfjSxlJjyEGEJNEMPkNBS8XMXxG47+oRrTn9pHNVqkkA1g9TB7AJRSdiVhT0n5PfaUX73SBE2HzNOxB7dX6lUFbTtzjUNlJm40f4DBdkGEcmBMQZG8ffQbe50VS/e4e7DYX6bunxskf/9ROUcKwY43hFnP9S+RPE78QRsWkmfhxpNqXkJnQNodeNEJ3N05XmtNFjCdg+T67ldAHrZ6blYKC5J09p27T+Gp2WdOEDEKcgaOZQvgi6MC+mbxRlnIJKpAFM0y6TlrA/9leSX/aikqhcxiUf7mGKO0BfaCAbAQLkw5w=</certificate>
+ </certificateChain>
+ <signature>kkkPeRx5aAXw12nl76Z/3cZ8qRptNQTFKY1KTXv2Vfei0gfmBKgGcLhPrb8uGcIBQUL4KYQsCjCS7MhZ+sWuCYMkTXv9Vi/pwuRuBFxzC7fhWs8YDzGQKilj+iYNpRcJdAJBsIanGFm+xYF2sRj5c/vew+NWsC4pUKHAEsdkkdg=</signature>
+</o-ex:rights>
diff --git a/test/sample_contents/RO/dtapps.db b/test/sample_contents/RO/dtapps.db
new file mode 100644
index 0000000..68d9558
--- /dev/null
+++ b/test/sample_contents/RO/dtapps.db
Binary files differ
diff --git a/test/sample_contents/RO/lXs4HhBlYZ.cert_only_selfsigned.ro b/test/sample_contents/RO/lXs4HhBlYZ.cert_only_selfsigned.ro
new file mode 100644
index 0000000..4019c0b
--- /dev/null
+++ b/test/sample_contents/RO/lXs4HhBlYZ.cert_only_selfsigned.ro
@@ -0,0 +1,36 @@
+<o-ex:rights xmlns:o-ex="http://odrl.net/1.1/ODRL-EX" xmlns:o-dd="http://odrl.net/1.1/ODRL-DD" xmlns:oma-dd="http://www.openmobilealliance.com/oma-dd" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" o-ex:id="SAD-RO2.0">
+ <o-ex:context>
+ <o-dd:version>2.0</o-dd:version>
+ <o-dd:uid>9de94f58e94f5c937d661eb0e6b2fe629200da82fb04d5f31a3d58543cd62c955f723a8f1ddf9f9e902aa0293c4e87c4f056a357d645f5f06e2676749ab838e6</o-dd:uid>
+ </o-ex:context>
+ <o-ex:agreement>
+ <o-ex:asset>
+ <o-ex:context>
+ <o-dd:uid>lXs4HhBlYZ-2.0.0</o-dd:uid>
+ </o-ex:context>
+ <ds:KeyInfo>
+ <xenc:EncryptedKey>
+ <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#kw-aes128"/>
+ <xenc:CipherData>
+ <xenc:CipherValue>AHRxoQ4tTUWtWpzkhktRY9rMTaQXW0UVnoZ4Vj7iacA=</xenc:CipherValue>
+ </xenc:CipherData>
+ </xenc:EncryptedKey>
+ </ds:KeyInfo>
+ </o-ex:asset>
+ <o-ex:permission>
+ <o-dd:execute>
+ <o-ex:constraint>
+ <o-dd:individual>
+ <o-ex:context>
+ <o-dd:uid>IMEI:354706050048713</o-dd:uid>
+ </o-ex:context>
+ </o-dd:individual>
+ </o-ex:constraint>
+ </o-dd:execute>
+ </o-ex:permission>
+ </o-ex:agreement>
+ <certificateChain>
+ <certificate>MIIDhzCCAvCgAwIBAgIJAOuPXJj4AnB9MA0GCSqGSIb3DQEBBQUAMIGKMQswCQYDVQQGEwJLTzEOMAwGA1UECBMFU2VvdWwxDTALBgNVBAoTBElOS0ExIjAgBgNVBAsTGUZvciBUZXN0aW5nIFB1cnBvc2VzIE9ubHkxFzAVBgNVBAMTDklOS0EgVGVzdCBSb290MR8wHQYJKoZIhvcNAQkBFhBtcmF3c0BpbmthLmNvLmtyMB4XDTExMDMxODAwMzc0MVoXDTIxMDMxNTAwMzc0MVowgYoxCzAJBgNVBAYTAktPMQ4wDAYDVQQIEwVTZW91bDENMAsGA1UEChMESU5LQTEiMCAGA1UECxMZRm9yIFRlc3RpbmcgUHVycG9zZXMgT25seTEXMBUGA1UEAxMOSU5LQSBUZXN0IFJvb3QxHzAdBgkqhkiG9w0BCQEWEG1yYXdzQGlua2EuY28ua3IwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMVIStQdSk7U94YWO2J3fGZ8k7VyFWlSc78esNRmKVZbH6nNBSvQVNTzBF4kPrPJPzBUwUeXA53W14RYgqVHueQtJhRk79cwG9fF2Y5BtGkqT4e+4l8N7qpI/T6GpIDviPgA2KwEoeEUgJZMcTN4cu/Umm9mCw/i+SBbD6RDtdnLAgMBAAGjgfIwge8wHQYDVR0OBBYEFCUSehbI1Emm6ygKCzr7wSgRr7QUMIG/BgNVHSMEgbcwgbSAFCUSehbI1Emm6ygKCzr7wSgRr7QUoYGQpIGNMIGKMQswCQYDVQQGEwJLTzEOMAwGA1UECBMFU2VvdWwxDTALBgNVBAoTBElOS0ExIjAgBgNVBAsTGUZvciBUZXN0aW5nIFB1cnBvc2VzIE9ubHkxFzAVBgNVBAMTDklOS0EgVGVzdCBSb290MR8wHQYJKoZIhvcNAQkBFhBtcmF3c0BpbmthLmNvLmtyggkA649cmPgCcH0wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBfM+S3GxC+aMVUHthO8t7bDeDauraJQADYd0wfwU1t/tOz4v17esH6uFC7XT/yMktf3+p+u/E6apYvxlSEIaRIIRGpdCbBrGH7ujX3Az2anMzJWRwSV9YKaM13peYl7O7kH79kbgQ72646bDR0dU+rUF5UdPDhqvl97dgPLVoyFg==</certificate>
+ </certificateChain>
+ <signature>XOMVIFVMhzHvQqrLq/SQnCT2881U6zmUhyrDMbrUyQ6U7zpiqFp0bthTOizCxdDoyaP4r047H9XCGf/JVeGDWVxqySqIublj5UcoL3g1IiOAu+99UrCCMgWJtmjQm+VC0lNh44615Xnhdve0Le6Qk3BagG8onVBtmEGuOyLjqI8=</signature>
+</o-ex:rights>
diff --git a/test/sample_contents/RO/lXs4HhBlYZ.ro b/test/sample_contents/RO/lXs4HhBlYZ.ro
new file mode 100644
index 0000000..ce38afc
--- /dev/null
+++ b/test/sample_contents/RO/lXs4HhBlYZ.ro
@@ -0,0 +1,37 @@
+<o-ex:rights xmlns:o-ex="http://odrl.net/1.1/ODRL-EX" xmlns:o-dd="http://odrl.net/1.1/ODRL-DD" xmlns:oma-dd="http://www.openmobilealliance.com/oma-dd" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" o-ex:id="SAD-RO2.0">
+ <o-ex:context>
+ <o-dd:version>2.0</o-dd:version>
+ <o-dd:uid>9de94f58e94f5c937d661eb0e6b2fe629200da82fb04d5f31a3d58543cd62c955f723a8f1ddf9f9e902aa0293c4e87c4f056a357d645f5f06e2676749ab838e6</o-dd:uid>
+ </o-ex:context>
+ <o-ex:agreement>
+ <o-ex:asset>
+ <o-ex:context>
+ <o-dd:uid>lXs4HhBlYZ-2.0.0</o-dd:uid>
+ </o-ex:context>
+ <ds:KeyInfo>
+ <xenc:EncryptedKey>
+ <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#kw-aes128"/>
+ <xenc:CipherData>
+ <xenc:CipherValue>AHRxoQ4tTUWtWpzkhktRY9rMTaQXW0UVnoZ4Vj7iacA=</xenc:CipherValue>
+ </xenc:CipherData>
+ </xenc:EncryptedKey>
+ </ds:KeyInfo>
+ </o-ex:asset>
+ <o-ex:permission>
+ <o-dd:execute>
+ <o-ex:constraint>
+ <o-dd:individual>
+ <o-ex:context>
+ <o-dd:uid>IMEI:354706050048713</o-dd:uid>
+ </o-ex:context>
+ </o-dd:individual>
+ </o-ex:constraint>
+ </o-dd:execute>
+ </o-ex:permission>
+ </o-ex:agreement>
+ <certificateChain>
+ <certificate>MIIEXDCCA0SgAwIBAgIBRzANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTExMDIxMTAzMTAzMFoXDTMxMDIwNjAzMTAzMFowaDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxHjAcBgNVBAsTFU1lZGlhIFNvbHV0aW9uIENlbnRlcjEbMBkGA1UEAxMSRFJNKEFTVE9SRTItSU4tMDApMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhQisSmZqzucRFG8ckX4NtZgJSxdahP0OmKdRUoF3zxSrKXmiWj7fLRcj1puufn5TlikOVQmXwFPliqV90bUmOWHvc06Z8Sv2pdDas3foZ2pSDs+MZS1XTjhLkLTwkiNYFnzYepW2JueMF+EXZfWLKWCUK2sNvJux8dQcwhJIHZwIDAQABo4IBdzCCAXMwRgYIKwYBBQUHAQEEOjA4MDYGCCsGAQUFBzABhipodHRwOi8vcHViLm9zcHNlcnZlci5uZXQvc2VjdXJpdHkvc2NhL29jc3AwCQYDVR0TBAIwADCCAQ8GA1UdHwSCAQYwggECMIH/oHGgb4ZtbGRhcDovLzIxMC4xMTguNTcuMjk6Mzg5L0NOPWRwMSxPVT1NZWRpYSBTb2x1dGlvbiBDZW50ZXIsTz1TYW1zdW5nIEVsZWN0cm9uaWNzLEM9S1I/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdKKBiaSBhjCBgzEmMCQGA1UEAwwdU2Ftc3VuZyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxLjAsBgNVBAsMJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxHDAaBgNVBAoME1NhbXN1bmcgRWxlY3Ryb25pY3MxCzAJBgNVBAYTAktSMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQUFAAOCAQEAgX10I66EwTMdLNBiC6LRwFwDCaAbht6PsNeH0jvyph7d9gReNyJ0O15y+GFoFX3ta0K4xaf6qUcSg+8lRgkuMCxdMSqzN1e1ytmiLG/KQszXC2RtIEkSTe9DRh2u/Ozx5UwEL0ZO9MpTTlcti26MJ2dCbkfD2RHHqoQb5dJgUq2l8nAKVIWARjz3fdTdTbvqErTyUx7Oysch9nhu8OyymoLgoMI42kalgundQF6yYk+1XV34V72lM+z+9kak35pl9+j6XHA2S2HsyPN6JLzQfRxN05Kotyo5sHkNRX/fsTNe/xDOlDQccCf7uKZp9zwonBQB2XG6eZhI3hy7WLRb4Q==</certificate>
+ <certificate>MIIEFTCCAv2gAwIBAgIBADANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxKzApBgNVBAMTIlNhbXN1bmcgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDkxMTAyMDI1NDIwWhcNMjAxMDMwMDI1NDIwWjCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0bkji6Mggsv+hEUFd6FCLOUp0fXlqyGNzND/iD0KzeHfxiNkne55lpEpMQ8RR2Mk0oIMru8slnmlQe4G+Wi4ejuA+thpwtmcMHbiABk/1gb59agHEgiAWCYyGBtwTlNvjoC17pR7qTXp54LeDlinOVdqrr8KuDfxrD23IzkWoDFvTBxgh4Je86NMgG9CNoPcWgsFH2NSbmHlGMJGhQNyrzu9N8kT5RNdhZ3YA6y2Op1O2W61bCMoFaCxYuJBoF834umMX1QpMLdPyhDWvyRQF8eyrujk/lbxKFoUtoQdWo92wkH9fJzPbcrjzV08T0Zzv0ZMqI+cG1NUq4JGXJCztwIDAQABo4GMMIGJMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgH+MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUkjW5KAWZqeoa1Zc7sPtsrAhvbIUwHwYDVR0jBBgwFoAUdSvSt/cYuTKeXokzT+hjkv6fjVYwDQYJKoZIhvcNAQEFBQADggEBALoBA2T15qfVXYfaJaWeLNrM/68u7MeBX9zWfFLHIfjSxlJjyEGEJNEMPkNBS8XMXxG47+oRrTn9pHNVqkkA1g9TB7AJRSdiVhT0n5PfaUX73SBE2HzNOxB7dX6lUFbTtzjUNlJm40f4DBdkGEcmBMQZG8ffQbe50VS/e4e7DYX6bunxskf/9ROUcKwY43hFnP9S+RPE78QRsWkmfhxpNqXkJnQNodeNEJ3N05XmtNFjCdg+T67ldAHrZ6blYKC5J09p27T+Gp2WdOEDEKcgaOZQvgi6MC+mbxRlnIJKpAFM0y6TlrA/9leSX/aikqhcxiUf7mGKO0BfaCAbAQLkw5w=</certificate>
+ </certificateChain>
+ <signature>XOMVIFVMhzHvQqrLq/SQnCT2881U6zmUhyrDMbrUyQ6U7zpiqFp0bthTOizCxdDoyaP4r047H9XCGf/JVeGDWVxqySqIublj5UcoL3g1IiOAu+99UrCCMgWJtmjQm+VC0lNh44615Xnhdve0Le6Qk3BagG8onVBtmEGuOyLjqI8=</signature>
+</o-ex:rights>
diff --git a/test/sample_contents/RO/lXs4HhBlYZ.signature_invalid.ro b/test/sample_contents/RO/lXs4HhBlYZ.signature_invalid.ro
new file mode 100644
index 0000000..1a835af
--- /dev/null
+++ b/test/sample_contents/RO/lXs4HhBlYZ.signature_invalid.ro
@@ -0,0 +1,37 @@
+<o-ex:rights xmlns:o-ex="http://odrl.net/1.1/ODRL-EX" xmlns:o-dd="http://odrl.net/1.1/ODRL-DD" xmlns:oma-dd="http://www.openmobilealliance.com/oma-dd" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" o-ex:id="SAD-RO2.0">
+ <o-ex:context>
+ <o-dd:version>2.0</o-dd:version>
+ <o-dd:uid>9de94f58e94f5c937d661eb0e6b2fe629200da82fb04d5f31a3d58543cd62c955f723a8f1ddf9f9e902aa0293c4e87c4f056a357d645f5f06e2676749ab838e6</o-dd:uid>
+ </o-ex:context>
+ <o-ex:agreement>
+ <o-ex:asset>
+ <o-ex:context>
+ <o-dd:uid>lXs4HhBlYZ-2.0.0</o-dd:uid>
+ </o-ex:context>
+ <ds:KeyInfo>
+ <xenc:EncryptedKey>
+ <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#kw-aes128"/>
+ <xenc:CipherData>
+ <xenc:CipherValue>AHRxoQ4tTUWtWpzkhktRY9rMTaQXW0UVnoZ4Vj7iacA=</xenc:CipherValue>
+ </xenc:CipherData>
+ </xenc:EncryptedKey>
+ </ds:KeyInfo>
+ </o-ex:asset>
+ <o-ex:permission>
+ <o-dd:execute>
+ <o-ex:constraint>
+ <o-dd:individual>
+ <o-ex:context>
+ <o-dd:uid>IMEI:354706050048713</o-dd:uid>
+ </o-ex:context>
+ </o-dd:individual>
+ </o-ex:constraint>
+ </o-dd:execute>
+ </o-ex:permission>
+ </o-ex:agreement>
+ <certificateChain>
+ <certificate>MIIEXDCCA0SgAwIBAgIBRzANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTExMDIxMTAzMTAzMFoXDTMxMDIwNjAzMTAzMFowaDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxHjAcBgNVBAsTFU1lZGlhIFNvbHV0aW9uIENlbnRlcjEbMBkGA1UEAxMSRFJNKEFTVE9SRTItSU4tMDApMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhQisSmZqzucRFG8ckX4NtZgJSxdahP0OmKdRUoF3zxSrKXmiWj7fLRcj1puufn5TlikOVQmXwFPliqV90bUmOWHvc06Z8Sv2pdDas3foZ2pSDs+MZS1XTjhLkLTwkiNYFnzYepW2JueMF+EXZfWLKWCUK2sNvJux8dQcwhJIHZwIDAQABo4IBdzCCAXMwRgYIKwYBBQUHAQEEOjA4MDYGCCsGAQUFBzABhipodHRwOi8vcHViLm9zcHNlcnZlci5uZXQvc2VjdXJpdHkvc2NhL29jc3AwCQYDVR0TBAIwADCCAQ8GA1UdHwSCAQYwggECMIH/oHGgb4ZtbGRhcDovLzIxMC4xMTguNTcuMjk6Mzg5L0NOPWRwMSxPVT1NZWRpYSBTb2x1dGlvbiBDZW50ZXIsTz1TYW1zdW5nIEVsZWN0cm9uaWNzLEM9S1I/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdKKBiaSBhjCBgzEmMCQGA1UEAwwdU2Ftc3VuZyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxLjAsBgNVBAsMJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxHDAaBgNVBAoME1NhbXN1bmcgRWxlY3Ryb25pY3MxCzAJBgNVBAYTAktSMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQUFAAOCAQEAgX10I66EwTMdLNBiC6LRwFwDCaAbht6PsNeH0jvyph7d9gReNyJ0O15y+GFoFX3ta0K4xaf6qUcSg+8lRgkuMCxdMSqzN1e1ytmiLG/KQszXC2RtIEkSTe9DRh2u/Ozx5UwEL0ZO9MpTTlcti26MJ2dCbkfD2RHHqoQb5dJgUq2l8nAKVIWARjz3fdTdTbvqErTyUx7Oysch9nhu8OyymoLgoMI42kalgundQF6yYk+1XV34V72lM+z+9kak35pl9+j6XHA2S2HsyPN6JLzQfRxN05Kotyo5sHkNRX/fsTNe/xDOlDQccCf7uKZp9zwonBQB2XG6eZhI3hy7WLRb4Q==</certificate>
+ <certificate>MIIEFTCCAv2gAwIBAgIBADANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxKzApBgNVBAMTIlNhbXN1bmcgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDkxMTAyMDI1NDIwWhcNMjAxMDMwMDI1NDIwWjCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0bkji6Mggsv+hEUFd6FCLOUp0fXlqyGNzND/iD0KzeHfxiNkne55lpEpMQ8RR2Mk0oIMru8slnmlQe4G+Wi4ejuA+thpwtmcMHbiABk/1gb59agHEgiAWCYyGBtwTlNvjoC17pR7qTXp54LeDlinOVdqrr8KuDfxrD23IzkWoDFvTBxgh4Je86NMgG9CNoPcWgsFH2NSbmHlGMJGhQNyrzu9N8kT5RNdhZ3YA6y2Op1O2W61bCMoFaCxYuJBoF834umMX1QpMLdPyhDWvyRQF8eyrujk/lbxKFoUtoQdWo92wkH9fJzPbcrjzV08T0Zzv0ZMqI+cG1NUq4JGXJCztwIDAQABo4GMMIGJMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgH+MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUkjW5KAWZqeoa1Zc7sPtsrAhvbIUwHwYDVR0jBBgwFoAUdSvSt/cYuTKeXokzT+hjkv6fjVYwDQYJKoZIhvcNAQEFBQADggEBALoBA2T15qfVXYfaJaWeLNrM/68u7MeBX9zWfFLHIfjSxlJjyEGEJNEMPkNBS8XMXxG47+oRrTn9pHNVqkkA1g9TB7AJRSdiVhT0n5PfaUX73SBE2HzNOxB7dX6lUFbTtzjUNlJm40f4DBdkGEcmBMQZG8ffQbe50VS/e4e7DYX6bunxskf/9ROUcKwY43hFnP9S+RPE78QRsWkmfhxpNqXkJnQNodeNEJ3N05XmtNFjCdg+T67ldAHrZ6blYKC5J09p27T+Gp2WdOEDEKcgaOZQvgi6MC+mbxRlnIJKpAFM0y6TlrA/9leSX/aikqhcxiUf7mGKO0BfaCAbAQLkw5w=</certificate>
+ </certificateChain>
+ <signature>XOMVIFVMhzHvQqrLq/SQnCT2881UkkkUhyrDMbrUyQ6U7zpiqFp0bthTOizCxdDoyaP4r047H9XCGf/JVeGDWVxqySqIublj5UcoL3g1IiOAu+99UrCCMgWJtmjQm+VC0lNh44615Xnhdve0Le6Qk3BagG8onVBtmEGuOyLjqI8=</signature>
+</o-ex:rights>
diff --git a/test/sample_contents/ROv2/sample_1.ro b/test/sample_contents/ROv2/sample_1.ro
new file mode 100644
index 0000000..c214ff9
--- /dev/null
+++ b/test/sample_contents/ROv2/sample_1.ro
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<TizenLicense>
+<LicenseInfo>
+ <version>2.0</version>
+ <uid>021812eea564834d93dc9f218416479f22b7ef11b71e70270ae41bf9a9f8e605edd154e2d2df2f5b61befbf0e3a3d57ebbfac608a4506114f026f36d1d3fc7ce</uid>
+</LicenseInfo>
+<ContentInfo>
+ <cid>h801jungmi-2.1.0</cid>
+</ContentInfo>
+<KeyInfo>
+ <CipherValue>D8zc9v4bR22sf1UrfAFAz/Yuyh4mb0TVqpikr4nGC8U=</CipherValue>
+</KeyInfo>
+<DeviceInfo>
+ <DUID>DUID:njkbucn1dogaw</DUID>
+</DeviceInfo>
+<CertificateChain>
+ <Certificate>MIIEXDCCA0SgAwIBAgIBRzANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTExMDIxMTAzMTAzMFoXDTMxMDIwNjAzMTAzMFowaDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxHjAcBgNVBAsTFU1lZGlhIFNvbHV0aW9uIENlbnRlcjEbMBkGA1UEAxMSRFJNKEFTVE9SRTItSU4tMDApMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhQisSmZqzucRFG8ckX4NtZgJSxdahP0OmKdRUoF3zxSrKXmiWj7fLRcj1puufn5TlikOVQmXwFPliqV90bUmOWHvc06Z8Sv2pdDas3foZ2pSDs+MZS1XTjhLkLTwkiNYFnzYepW2JueMF+EXZfWLKWCUK2sNvJux8dQcwhJIHZwIDAQABo4IBdzCCAXMwRgYIKwYBBQUHAQEEOjA4MDYGCCsGAQUFBzABhipodHRwOi8vcHViLm9zcHNlcnZlci5uZXQvc2VjdXJpdHkvc2NhL29jc3AwCQYDVR0TBAIwADCCAQ8GA1UdHwSCAQYwggECMIH/oHGgb4ZtbGRhcDovLzIxMC4xMTguNTcuMjk6Mzg5L0NOPWRwMSxPVT1NZWRpYSBTb2x1dGlvbiBDZW50ZXIsTz1TYW1zdW5nIEVsZWN0cm9uaWNzLEM9S1I/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdKKBiaSBhjCBgzEmMCQGA1UEAwwdU2Ftc3VuZyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxLjAsBgNVBAsMJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxHDAaBgNVBAoME1NhbXN1bmcgRWxlY3Ryb25pY3MxCzAJBgNVBAYTAktSMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQUFAAOCAQEAgX10I66EwTMdLNBiC6LRwFwDCaAbht6PsNeH0jvyph7d9gReNyJ0O15y+GFoFX3ta0K4xaf6qUcSg+8lRgkuMCxdMSqzN1e1ytmiLG/KQszXC2RtIEkSTe9DRh2u/Ozx5UwEL0ZO9MpTTlcti26MJ2dCbkfD2RHHqoQb5dJgUq2l8nAKVIWARjz3fdTdTbvqErTyUx7Oysch9nhu8OyymoLgoMI42kalgundQF6yYk+1XV34V72lM+z+9kak35pl9+j6XHA2S2HsyPN6JLzQfRxN05Kotyo5sHkNRX/fsTNe/xDOlDQccCf7uKZp9zwonBQB2XG6eZhI3hy7WLRb4Q==</Certificate>
+ <Certificate>MIIEFTCCAv2gAwIBAgIBADANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxKzApBgNVBAMTIlNhbXN1bmcgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDkxMTAyMDI1NDIwWhcNMjAxMDMwMDI1NDIwWjCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0bkji6Mggsv+hEUFd6FCLOUp0fXlqyGNzND/iD0KzeHfxiNkne55lpEpMQ8RR2Mk0oIMru8slnmlQe4G+Wi4ejuA+thpwtmcMHbiABk/1gb59agHEgiAWCYyGBtwTlNvjoC17pR7qTXp54LeDlinOVdqrr8KuDfxrD23IzkWoDFvTBxgh4Je86NMgG9CNoPcWgsFH2NSbmHlGMJGhQNyrzu9N8kT5RNdhZ3YA6y2Op1O2W61bCMoFaCxYuJBoF834umMX1QpMLdPyhDWvyRQF8eyrujk/lbxKFoUtoQdWo92wkH9fJzPbcrjzV08T0Zzv0ZMqI+cG1NUq4JGXJCztwIDAQABo4GMMIGJMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgH+MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUkjW5KAWZqeoa1Zc7sPtsrAhvbIUwHwYDVR0jBBgwFoAUdSvSt/cYuTKeXokzT+hjkv6fjVYwDQYJKoZIhvcNAQEFBQADggEBALoBA2T15qfVXYfaJaWeLNrM/68u7MeBX9zWfFLHIfjSxlJjyEGEJNEMPkNBS8XMXxG47+oRrTn9pHNVqkkA1g9TB7AJRSdiVhT0n5PfaUX73SBE2HzNOxB7dX6lUFbTtzjUNlJm40f4DBdkGEcmBMQZG8ffQbe50VS/e4e7DYX6bunxskf/9ROUcKwY43hFnP9S+RPE78QRsWkmfhxpNqXkJnQNodeNEJ3N05XmtNFjCdg+T67ldAHrZ6blYKC5J09p27T+Gp2WdOEDEKcgaOZQvgi6MC+mbxRlnIJKpAFM0y6TlrA/9leSX/aikqhcxiUf7mGKO0BfaCAbAQLkw5w=</Certificate>
+</CertificateChain>
+<SignatureValue>lWthdDZsTFJG2dq6vOXUJU5LwgXwPCfE38Pdw7xrNeNoVylyDNzkavYB7A+LDlaLtjt1gNPxVm8N5dgRJjwXGJoVFnkW3csYSjr0/CLkBnXof+od6BuCAy3hVNjrZRtn6N1y+V6he01PmwMcnoBnWl+ej3HYK89WnUmYjJXg9vU=</SignatureValue>
+</TizenLicense>
diff --git a/test/sample_contents/ROv2/sample_2.ro b/test/sample_contents/ROv2/sample_2.ro
new file mode 100644
index 0000000..2992be9
--- /dev/null
+++ b/test/sample_contents/ROv2/sample_2.ro
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<TizenLicense>
+<LicenseInfo>
+ <version>2.0</version>
+ <uid>64304c362d54383df4a15c01a198b2915f3feff38486c48c4da63647d36e387f14ff7c85b10d8c87e013d7cab0eaeb3e7ba9f7b90bb3d068b9fdca1c12fc89c1</uid>
+</LicenseInfo>
+<ContentInfo>
+ <cid>JBJ08270001-2.1.0</cid>
+</ContentInfo>
+<KeyInfo>
+ <CipherValue>3rDuE1WNSvubcHSQgyOgRqbzTycHwE0pgJmsajUubVs=</CipherValue>
+</KeyInfo>
+<DeviceInfo>
+ <DUID>DUID:njkbucn1dogaw</DUID>
+</DeviceInfo>
+<CertificateChain>
+ <Certificate>MIIEXDCCA0SgAwIBAgIBRzANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTExMDIxMTAzMTAzMFoXDTMxMDIwNjAzMTAzMFowaDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxHjAcBgNVBAsTFU1lZGlhIFNvbHV0aW9uIENlbnRlcjEbMBkGA1UEAxMSRFJNKEFTVE9SRTItSU4tMDApMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhQisSmZqzucRFG8ckX4NtZgJSxdahP0OmKdRUoF3zxSrKXmiWj7fLRcj1puufn5TlikOVQmXwFPliqV90bUmOWHvc06Z8Sv2pdDas3foZ2pSDs+MZS1XTjhLkLTwkiNYFnzYepW2JueMF+EXZfWLKWCUK2sNvJux8dQcwhJIHZwIDAQABo4IBdzCCAXMwRgYIKwYBBQUHAQEEOjA4MDYGCCsGAQUFBzABhipodHRwOi8vcHViLm9zcHNlcnZlci5uZXQvc2VjdXJpdHkvc2NhL29jc3AwCQYDVR0TBAIwADCCAQ8GA1UdHwSCAQYwggECMIH/oHGgb4ZtbGRhcDovLzIxMC4xMTguNTcuMjk6Mzg5L0NOPWRwMSxPVT1NZWRpYSBTb2x1dGlvbiBDZW50ZXIsTz1TYW1zdW5nIEVsZWN0cm9uaWNzLEM9S1I/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdKKBiaSBhjCBgzEmMCQGA1UEAwwdU2Ftc3VuZyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxLjAsBgNVBAsMJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxHDAaBgNVBAoME1NhbXN1bmcgRWxlY3Ryb25pY3MxCzAJBgNVBAYTAktSMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQUFAAOCAQEAgX10I66EwTMdLNBiC6LRwFwDCaAbht6PsNeH0jvyph7d9gReNyJ0O15y+GFoFX3ta0K4xaf6qUcSg+8lRgkuMCxdMSqzN1e1ytmiLG/KQszXC2RtIEkSTe9DRh2u/Ozx5UwEL0ZO9MpTTlcti26MJ2dCbkfD2RHHqoQb5dJgUq2l8nAKVIWARjz3fdTdTbvqErTyUx7Oysch9nhu8OyymoLgoMI42kalgundQF6yYk+1XV34V72lM+z+9kak35pl9+j6XHA2S2HsyPN6JLzQfRxN05Kotyo5sHkNRX/fsTNe/xDOlDQccCf7uKZp9zwonBQB2XG6eZhI3hy7WLRb4Q==</Certificate>
+ <Certificate>MIIEFTCCAv2gAwIBAgIBADANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxKzApBgNVBAMTIlNhbXN1bmcgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDkxMTAyMDI1NDIwWhcNMjAxMDMwMDI1NDIwWjCBgzELMAkGA1UEBhMCS1IxHDAaBgNVBAoTE1NhbXN1bmcgRWxlY3Ryb25pY3MxLjAsBgNVBAsTJVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IENlbnRyYWwxJjAkBgNVBAMTHVNhbXN1bmcgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0bkji6Mggsv+hEUFd6FCLOUp0fXlqyGNzND/iD0KzeHfxiNkne55lpEpMQ8RR2Mk0oIMru8slnmlQe4G+Wi4ejuA+thpwtmcMHbiABk/1gb59agHEgiAWCYyGBtwTlNvjoC17pR7qTXp54LeDlinOVdqrr8KuDfxrD23IzkWoDFvTBxgh4Je86NMgG9CNoPcWgsFH2NSbmHlGMJGhQNyrzu9N8kT5RNdhZ3YA6y2Op1O2W61bCMoFaCxYuJBoF834umMX1QpMLdPyhDWvyRQF8eyrujk/lbxKFoUtoQdWo92wkH9fJzPbcrjzV08T0Zzv0ZMqI+cG1NUq4JGXJCztwIDAQABo4GMMIGJMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgH+MCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUkjW5KAWZqeoa1Zc7sPtsrAhvbIUwHwYDVR0jBBgwFoAUdSvSt/cYuTKeXokzT+hjkv6fjVYwDQYJKoZIhvcNAQEFBQADggEBALoBA2T15qfVXYfaJaWeLNrM/68u7MeBX9zWfFLHIfjSxlJjyEGEJNEMPkNBS8XMXxG47+oRrTn9pHNVqkkA1g9TB7AJRSdiVhT0n5PfaUX73SBE2HzNOxB7dX6lUFbTtzjUNlJm40f4DBdkGEcmBMQZG8ffQbe50VS/e4e7DYX6bunxskf/9ROUcKwY43hFnP9S+RPE78QRsWkmfhxpNqXkJnQNodeNEJ3N05XmtNFjCdg+T67ldAHrZ6blYKC5J09p27T+Gp2WdOEDEKcgaOZQvgi6MC+mbxRlnIJKpAFM0y6TlrA/9leSX/aikqhcxiUf7mGKO0BfaCAbAQLkw5w=</Certificate>
+</CertificateChain>
+<SignatureValue>MFghtps+Q9q5r82d/+wjqVM5NBdy4Q2xy9N6xjV5fl8zuhE/Ya4mEYE7lx3YlIHFTJIW2DfvHvc8VSICKeL7yuln4arwDPT83SKoymArIXx54PLLmzGCI58kPQX5NWOQDAWxHPBLyfNK2vgN00jwqqRxJZkSSZAu4c0/XnTDMRk=</SignatureValue>
+</TizenLicense>