initial version 75/39875/8
authorDongsun Lee <ds73.lee@samsung.com>
Tue, 26 May 2015 00:42:38 +0000 (09:42 +0900)
committerDongsun Lee <ds73.lee@samsung.com>
Fri, 24 Jul 2015 01:58:41 +0000 (10:58 +0900)
Change-Id: Ibb7891bee67bdd82f34187f5da2fc3c4bbfa8fcd
Signed-off-by: Dongsun Lee <ds73.lee@samsung.com>
25 files changed:
AUTHORS [new file with mode: 0644]
CMakeLists.txt [new file with mode: 0644]
LICENSE.Apache-2.0 [new file with mode: 0644]
build/CMakeLists.txt [new file with mode: 0644]
build/libwebappenc.pc.in [new file with mode: 0644]
include/CMakeLists.txt [new file with mode: 0644]
include/web_app_enc.h [new file with mode: 0644]
packaging/libwebappenc.manifest [new file with mode: 0644]
packaging/libwebappenc.spec [new file with mode: 0644]
resources/CMakeLists.txt [new file with mode: 0644]
resources/README_APP_DEK [new file with mode: 0644]
resources/WAE_APPDEK_KEK_PrivateKey.pem [new file with mode: 0644]
resources/WAE_APPDEK_KEK_PublicKey.pem [new file with mode: 0644]
srcs/CMakeLists.txt [new file with mode: 0644]
srcs/crypto_service.c [new file with mode: 0644]
srcs/crypto_service.h [new file with mode: 0644]
srcs/key_handler.c [new file with mode: 0644]
srcs/key_handler.h [new file with mode: 0644]
srcs/wae_initializer.c [new file with mode: 0644]
srcs/wae_log.h [new file with mode: 0644]
srcs/web_app_enc.c [new file with mode: 0644]
systemd/CMakeLists.txt [new file with mode: 0644]
systemd/webappenc-initializer.service.in [new file with mode: 0644]
tests/CMakeLists.txt [new file with mode: 0644]
tests/wae_tests.c [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..ab6e400
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Dongsun Lee <ds73.lee@samsung.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..c9fec0e
--- /dev/null
@@ -0,0 +1,93 @@
+# Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+# @file        CMakeLists.txt
+# @author
+# @brief
+#
+
+############################# Check minimum CMake version #####################
+
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT("webappenc")
+
+SET(SO_VERSION 1)
+SET(VERSION "${SO_VERSION}.0.0")
+
+############################# cmake packages ##################################
+
+INCLUDE(FindPkgConfig)
+
+############################# 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")
+
+# If supported for the target machine, emit position-independent code,suitable
+# for dynamic linking and avoiding any limit on the size of the global offset
+# table. This option makes a difference on the m68k, PowerPC and SPARC.
+# (BJ: our ARM too?)
+ADD_DEFINITIONS("-fPIC")
+
+# Set compiler warning flags
+ADD_DEFINITIONS("-Werror")                      # Make all warnings into errors.
+ADD_DEFINITIONS("-Wall")                        # Generate all warnings
+ADD_DEFINITIONS("-Wextra")                      # Generate even more extra warnings
+
+STRING(REGEX MATCH "([^.]*)" API_VERSION "${VERSION}")
+ADD_DEFINITIONS("-DAPI_VERSION=\"$(API_VERSION)\"")
+ADD_DEFINITIONS("-DSMACK_ENABLED")
+ADD_DEFINITIONS("-DSQLCIPHER_HAS_CODEC")
+
+# IF (CMAKE_BUILD_TYPE MATCHES "DEBUG")
+    ADD_DEFINITIONS("-DTIZEN_DEBUG_ENABLE")
+    ADD_DEFINITIONS("-DBUILD_TYPE_DEBUG")
+# ENDIF (CMAKE_BUILD_TYPE MATCHES "DEBUG")
+
+################# common configurations for srcs and test ######################
+SET(DEPENDENTS "openssl dlog key-manager libtzplatform-config")
+PKG_CHECK_MODULES(WEB_APP_ENC_DEPS
+    REQUIRED
+    ${DEPENDENTS}
+)
+
+
+############################ For PC file setting  ################################
+SET(PC_NAME ${PROJECT_NAME})
+SET(PC_REQUIRED ${DEPENDENTS})
+SET(PC_LDFLAGS -l${PROJECT_NAME})
+#SET(PC_CFLAGS -I\${includedir})
+
+
+############################ Target Setting ################################
+SET(TARGET_WEBAPPENC ${PROJECT_NAME})
+SET(TARGET_WAE_INITIALIZER wae_initializer)
+SET(TARGET_WAE_ENCRYPTER wae_encrypter)
+SET(TARGET_WEBAPPENC_TEST wae_tests)
+
+############################ Add Sub Directories  ################################
+ADD_SUBDIRECTORY(srcs)
+ADD_SUBDIRECTORY(build)
+ADD_SUBDIRECTORY(resources)
+ADD_SUBDIRECTORY(include)
+ADD_SUBDIRECTORY(tests)
+ADD_SUBDIRECTORY(systemd)
+
+
diff --git a/LICENSE.Apache-2.0 b/LICENSE.Apache-2.0
new file mode 100644 (file)
index 0000000..247c97d
--- /dev/null
@@ -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/build/CMakeLists.txt b/build/CMakeLists.txt
new file mode 100644 (file)
index 0000000..338e7ce
--- /dev/null
@@ -0,0 +1,25 @@
+# Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+# @file        CMakeLists.txt
+# @brief
+#
+
+CONFIGURE_FILE(libwebappenc.pc.in libwebappenc.pc @ONLY)
+
+INSTALL(FILES
+    ${CMAKE_BINARY_DIR}/build/libwebappenc.pc
+    DESTINATION
+    ${LIB_INSTALL_DIR}/pkgconfig
+    )
diff --git a/build/libwebappenc.pc.in b/build/libwebappenc.pc.in
new file mode 100644 (file)
index 0000000..2af6c92
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@PREFIX@
+libdir=@PREFIX@/lib
+includedir=@PREFIX@/include
+
+Name: @PC_NAME@
+Description: Web application encryption and decryption service based on key-manager
+Version: @VERSION@
+Requires: @PC_REQUIRED@
+Libs: @PC_LDFLAGS@
+Cflags: @PC_CFLAGS@
+
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
new file mode 100644 (file)
index 0000000..26e801c
--- /dev/null
@@ -0,0 +1,4 @@
+INSTALL(FILES
+    ${CMAKE_CURRENT_SOURCE_DIR}/web_app_enc.h
+    DESTINATION ${INCLUDEDIR}
+    )
diff --git a/include/web_app_enc.h b/include/web_app_enc.h
new file mode 100644 (file)
index 0000000..2e31a3c
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ * @file    web_app_enc.h
+ * @version 1.0
+ * @brief   This file contains APIs of WEB_APP_ENC module.
+*/
+
+#ifndef __WEB_APP_ENC__
+#define __WEB_APP_ENC__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup CAPI_WEB_APP_ENC_MODULE
+ * @{
+ */
+
+
+typedef enum
+{
+    WAE_ERROR_NONE                     =   0x00, /**< Successful */
+    WAE_ERROR_INVALID_PARAMETER        = - 0x01, /**< Invalid function parameter */
+    WAE_ERROR_PERMISSION_DENIED        = - 0x02, /**< Permission denied */
+    WAE_ERROR_NO_KEY                   = - 0x03, /**< No key */
+    WAE_ERROR_KEY_EXISTS               = - 0x04, /**< key already exists*/
+    WAE_ERROR_KEY_MANAGER              = - 0x05, /**< key-manager internal error */
+    WAE_ERROR_CRYPTO                   = - 0x06, /**< failed in crypto operation */
+    WAE_ERROR_MEMORY                   = - 0x07, /**< failed to allocate memory */
+    WAE_ERROR_FILE                     = - 0x08, /**< failed to read or write a file*/
+    WAE_ERROR_UNKNOWN                  = - 0x09  /** < Unknown error */
+} wae_error_e;
+
+/**
+ * @brief Encrypts web application data with internal key(APP DEK: Application Data Encryption Key).
+ *
+ * @since_tizen 3.0
+ * @param[in] pPkgId   The package id of an application.
+ * @param[in] isPreloaded True(!=0) if the application is preloaded, otherwise false(==0).
+ * @param[in] pData    The data block to be encrypted.
+ * @param[in] dataLen  The length of the data block.
+ * @param[out] ppEncryptedData The data block contaning encrypted data block. Memory allocated for ppEncryptedData. Has to be freed by free() function.
+ * @param[out] pEncDataLen The length of the encrypted data block.
+ *
+ * @return #WAE_ERROR_NONE on success, otherwise a negative error value
+ * @retval #WAE_ERROR_INVALID_PARAMETER   Invalid input parameter
+ * @retval #WAE_ERROR_PERMISSION_DENIED   Non-authenticated application request
+ * @retval #WAE_ERROR_NO_KEY              No internal key
+ * @retval #WAE_ERROR_KEY_MANAGER         key-manager internal error
+ * @retval #WAE_ERROR_CRYPTO              failed in crypto operation
+ * @retval #WAE_ERROR_UNKNOWN             Failed with unknown reason
+ *
+ * @see wae_decrypt_web_application()
+ */
+int wae_encrypt_web_application(const char* pPkgId, int isPreloaded, const unsigned char* pData, size_t dataLen, unsigned char** ppEncryptedData, size_t* pEncDataLen);
+
+/**
+ * @brief Encrypts web application data with internal key.
+ *
+ * @since_tizen 3.0
+ * @param[in] pPkgId   The package id of an application.
+ * @param[in] isPreloaded True(!=0) if the application is preloaded, otherwise false(==0).
+ * @param[in] pData    The data block to be decrypted.
+ * @param[in] dataLen  The length of the data block.
+ * @param[out] ppDecryptedData Data block contaning decrypted data block. Memory allocated for ppEncryptedData. Has to be freed by free() function.
+ * @param[out] pDecDataLen The length of the decrypted data block.
+ *
+ * @return #WAE_ERROR_NONE on success, otherwise a negative error value
+ * @retval #WAE_ERROR_INVALID_PARAMETER   Invalid input parameter
+ * @retval #WAE_ERROR_PERMISSION_DENIED   Non-authenticated application request
+ * @retval #WAE_ERROR_NO_KEY              No internal key
+ * @retval #WAE_ERROR_KEY_MANAGER         key-manager internal error
+ * @retval #WAE_ERROR_CRYPTO              failed in crypto operation
+ * @retval #WAE_ERROR_UNKNOWN             Failed with unknown reason
+ *
+ * @see wae_encrypt_web_application()
+ */
+int wae_decrypt_web_application(const char* pPkgId, int isPreloaded, const unsigned char* pData, size_t dataLen, unsigned char** ppDecryptedData, size_t* pDecDataLen);
+
+/**
+ * @brief Remove a APP DEK(Application Data Encryption Key) used for encrytpion and decryption of a web application.
+ *
+ * @since_tizen 3.0
+ * @param[in] pPkgId   The package id of an application.
+ *
+ * @return #WAE_ERROR_NONE on success, otherwise a negative error value
+ * @retval #WAE_ERROR_INVALID_PARAMETER   Invalid input parameter
+ * @retval #WAE_ERROR_PERMISSION_DENIED   Non-authenticated application request
+ * @retval #WAE_ERROR_NO_KEY              No internal key
+ * @retval #WAE_ERROR_KEY_MANAGER         key-manager internal error
+ * @retval #WAE_ERROR_UNKNOWN             Failed with unknown reason
+ *
+ */
+int wae_remove_app_dek(const char* pPkgId);
+
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __WEB_APP_ENC__ */
+
diff --git a/packaging/libwebappenc.manifest b/packaging/libwebappenc.manifest
new file mode 100644 (file)
index 0000000..226aaa0
--- /dev/null
@@ -0,0 +1,8 @@
+<manifest>
+    <request>
+        <domain name="_" />
+    </request>
+    <assign>
+        <filesystem path="/var/libwebappenc/" label="System" />
+    </assign>
+</manifest>
diff --git a/packaging/libwebappenc.spec b/packaging/libwebappenc.spec
new file mode 100644 (file)
index 0000000..b3c2cbc
--- /dev/null
@@ -0,0 +1,115 @@
+Name:    libwebappenc
+Summary: Web application encryption service
+Version: 0.1.0
+Release: 1
+Group:   System/Libraries
+License: Apache-2.0
+Source0: %{name}-%{version}.tar.gz
+Source1001: %{name}.manifest
+
+Requires(post):   /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+BuildRequires: cmake
+BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(openssl)
+BuildRequires: pkgconfig(key-manager)
+BuildRequires: pkgconfig(libtzplatform-config)
+Requires: openssl
+Requires: pkgconfig(libtzplatform-config)
+
+%description
+Web application encryption and decryption service
+
+%package devel
+Summary:    Web application encryption service (development files)
+Group:      Development/Libraries
+Requires:   %{name} = %{version}-%{release}
+
+%description devel
+Web application encryption and decryption service (development files)
+
+%package test
+Summary:    Web application encryption service (test)
+Group:      Development
+Requires:   %{name} = %{version}-%{release}
+
+%description test
+Web application encryption and decryption service (test)
+
+
+
+%prep
+%setup -q
+cp %{SOURCE1001} .
+
+%build
+%{!?build_type:%define build_type "Release"}
+%cmake . -DPREFIX=%{_prefix} \
+         -DEXEC_PREFIX=%{_exec_prefix} \
+         -DINCLUDEDIR=%{_includedir} \
+         -DLIBDIR=%{_libdir} \
+         -DBINDIR=%TZ_SYS_BIN \
+         -DSYSTEMD_UNIT_DIR=%{_unitdir} \
+         -DCMAKE_BUILD_TYPE=%{build_type} \
+         -DTZ_SYS_BIN=%TZ_SYS_BIN \
+         -DTZ_SYS_SHARE=%TZ_SYS_SHARE
+
+make %{?jobs:-j%jobs}
+
+
+%install
+rm -rf %{buildroot}
+mkdir -p %{buildroot}%{TZ_SYS_SHARE}/license
+cp LICENSE.Apache-2.0 %{buildroot}%{TZ_SYS_SHARE}/license/%{name}
+%make_install
+mkdir -p %{buildroot}%{_unitdir}/multi-user.target.wants
+ln -s ../webappenc-initializer.service %{buildroot}%{_unitdir}/multi-user.target.wants/webappenc-initializer.service
+
+
+%clean
+rm -rf %{buildroot}
+
+%post
+/sbin/ldconfig
+systemctl daemon-reload
+if [ $1 = 1 ]; then
+    # installation
+    systemctl start webappenc-initializer.service
+fi
+
+if [ $1 = 2 ]; then
+    # update
+    systemctl restart webappenc-initializer.service
+fi
+
+%postun
+/sbin/ldconfig
+if [ $1 = 0 ]; then
+    # uninstall
+    systemctl daemon-reload
+fi
+
+
+%files
+%defattr(-,root,root,-)
+%manifest %{name}.manifest
+%{TZ_SYS_SHARE}/license/%{name}
+%{_libdir}/%{name}.so.*
+%{_unitdir}/webappenc-initializer.service
+%{_unitdir}/multi-user.target.wants/webappenc-initializer.service
+%{TZ_SYS_BIN}/wae_initializer
+%{TZ_SYS_SHARE}/wae/app_dek/WAE_APPDEK_KEK_PrivateKey.pem
+%{TZ_SYS_SHARE}/wae/app_dek/WAE_APPDEK_KEK_PublicKey.pem
+
+%files devel
+%defattr(-,root,root,-)
+%{_includedir}/*
+%{_libdir}/pkgconfig/%{name}.pc
+%{_libdir}/%{name}.so
+
+%files test
+%defattr(-,root,root,-)
+%{TZ_SYS_BIN}/wae_tests
+
+
diff --git a/resources/CMakeLists.txt b/resources/CMakeLists.txt
new file mode 100644 (file)
index 0000000..4462cee
--- /dev/null
@@ -0,0 +1,12 @@
+################################################################################
+# for resource install
+################################################################################
+
+INSTALL(FILES
+    ${PROJECT_SOURCE_DIR}/resources/WAE_APPDEK_KEK_PublicKey.pem
+    ${PROJECT_SOURCE_DIR}/resources/WAE_APPDEK_KEK_PrivateKey.pem
+    DESTINATION ${TZ_SYS_SHARE}/wae/app_dek/
+    PERMISSIONS OWNER_READ
+    OWNER_WRITE
+)
+
diff --git a/resources/README_APP_DEK b/resources/README_APP_DEK
new file mode 100644 (file)
index 0000000..724b8c2
--- /dev/null
@@ -0,0 +1 @@
+The directory, app_dek, contains APP_DEK files encrypted with APP_DEK_KEK public key.
diff --git a/resources/WAE_APPDEK_KEK_PrivateKey.pem b/resources/WAE_APPDEK_KEK_PrivateKey.pem
new file mode 100644 (file)
index 0000000..e27950c
--- /dev/null
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,F4C783D75B0679F29398E9A3CAB4733D
+
+kxgW1wGX3TZZ/wtv3g4AOLlZCHoQ6uXVQ0h2ofWjnJs8tas/alR6o8UBRIqCw44t
+znUvQ8HlThvzhGgxje/yDDSxCy9mqhgsi2XeTtAeUbMhFL6UArb3cs6M4a37lYoT
+llZdFyYkRWJ3vRS33TDrhXDV6GjZWQ05SJ0OYdPJsmA1ENwdH+5NE/xLnqLdTtWr
+O3Mn2vi6P9CVqZroCvYBzUaypGcmFhjTIbWmB6inXjoXyddzerh7PTDBDWWacBab
+C7gcZC5SrK5YOt6f54ANsVQO8jnkLDx95gUSHYthX1hrQ3Da5Gb6nfYP9RNrHCum
+O8RKxSOvv8zwbMlzqtld8xCOb7Nh04f8bofrzZVLZ0T92FcyFQmt1F4U6DNQqHsn
+AAqxRxUWsC5k2dX9uZ6RCpEzNYWyPvNe24I/Kt01Geoh1NtCns8CVZcrxyMMtZRK
+ZJnYhvNDXDQCDtMJjRBiEXXE++AdA2O6uFoGX3alKwtxAIjGI++pSRlz1GTps26x
+5mmLil5wb3KGBfMN4L0R0heDOeiPQrNv7CwX8OlHtA1OKFBtViWdd/uZ2hAko1Tz
+YkoYpHPQOV5LZ7dem/XNnwwel9g6AkHhLNJv5ih4Y0CQfPBSs+iiLbMHh/NaGDD9
++kbcf5Lk4FQGVbJDW9nDAXT6jjMyliTI+hIh5fM2k22qbq6OqBkW6EbOQDMP/R2P
+LhFqTgHceNt0mqpcDJdJQ0YKbxVpdkv5f1C4rW+pgUEeHDCQ7vPe4p44xQJ/Z/7Y
+AtPwPKzPPJze2cfoUkZd9jXN9g2v2555xnQZU78IEm1nPVBA+hLIaqN1hu1Lkzxy
+CwFNo7bMVh3FSBmZVtJlcLsyLxZ9UdoaSr+anfA0lWJPiBzE0whQljZp56l1rL1V
+1K8m/dc9rLJ3uDQmYoSRmBZG5zZlVWCip+R9VAHMxRi1x29dFk1jbtQscr63dMI8
+0eOUf28Mw719WWUZVzD08b431DPqWiqrpexUKEXPW8EsrINPfIg180QYt1VUoshs
+Tqi/LKM0OV6nlMGh9ieCK8WzVDW8F16krSLo6eJpIPYPZgkHE7fC7Jws1kpUrSnF
+GgT6rBA97tJ0EalinuFXbip1X087Quz5USURq18f7/B6nFu0Kd4GhlICsR24j3eB
+75SsTNmfUcko8s5QT4rwONEwtRffkGbbNEisCPcleJV68zHvN58mfD7Dl8W3zIO4
+Qk6B1Xy0C4EEniKFfjxIaMEaxrqntBIc+nZE6/+UoGp/Hj9r5ZdzQX2j4837IIdR
+CxT4tjXiWBA6u3WaLAZUSM0W0SEORUF9NwzlId1b8A3WxA8XewhAKPaJEr677vzZ
+083+neUOuXqqs597romLH1omuffxmHxBzmP+koUtemP78XxCBVWUAB1T+fBRJMz6
+9ZEgDWrMntJ1IaFoGdOWZELgwcXJ0KwWFuk+sieZ5WCCzNmFli9WPN/xSqwmdYw6
+RK9er5Vc8D9mAlmGlz2mpAmzNJHH30zYKT/d0XzBS8z6WBRthaTS3NLsiSeWdELH
+b5+WEMOiKvZ19AXU2unHw/XpeVnAISOHhumAqFCwXkjVoMt8LMDawt6ra8N8G+gD
+-----END RSA PRIVATE KEY-----
diff --git a/resources/WAE_APPDEK_KEK_PublicKey.pem b/resources/WAE_APPDEK_KEK_PublicKey.pem
new file mode 100644 (file)
index 0000000..f0dfcea
--- /dev/null
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0kWtjpRO7Zh2KX2naVE/
+BDJdrfwK9xexfNA0MkY2VJ4J2AKMYTj1D1jntceryupCEHOvP3rum+WsFvPXduz9
++VKnSsSqj4jcTUubtpDUGA5G79IqLEPFuSBaqI8Uwkzd08pE+s30oaJDnNazMhSq
+8JkqBPoCCwtUs73ruE9VbtsBO/kTlASIAfe8nXqcJLcDQgWYhizjJw0Pi6d74oCw
+S2OTvQDNvsXfFnA0ZJEEYw/rZLirj7OHoOjz+Sh5N+1uA3Up6SPPEbHuP6L12Yxq
+Hdy7gnJXodLhvE/cR4SN9VW7+qmCMBjmLkBejGrEX3STS9sLI7MZHu9Y26dwuYb4
++wIDAQAB
+-----END PUBLIC KEY-----
diff --git a/srcs/CMakeLists.txt b/srcs/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e94a7d4
--- /dev/null
@@ -0,0 +1,67 @@
+################################################################################
+# for libwebappenc.so
+################################################################################
+
+SET(WEB_APP_ENC_SOURCES
+    ${CMAKE_CURRENT_SOURCE_DIR}/web_app_enc.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/key_handler.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/crypto_service.c
+)
+
+INCLUDE_DIRECTORIES(
+    ${PROJECT_SOURCE_DIR}/include
+    ${WEB_APP_ENC_DEPS_INCLUDE_DIRS}
+)
+
+ADD_LIBRARY(${TARGET_WEBAPPENC} SHARED ${WEB_APP_ENC_SOURCES})
+
+SET_TARGET_PROPERTIES(${TARGET_WEBAPPENC} PROPERTIES
+    SOVERSION ${SO_VERSION}
+    VERSION ${VERSION}
+)
+
+TARGET_LINK_LIBRARIES(${TARGET_WEBAPPENC}
+    pthread
+    ${WEB_APP_ENC_DEPS_LIBRARIES}
+)
+
+INSTALL(TARGETS ${TARGET_WEBAPPENC}
+    DESTINATION ${LIBDIR})
+
+INSTALL(FILES ${PROJECT_SOURCE_DIR}/include/web_app_enc.h
+    DESTINATION ${INCLUDEDIR})
+
+
+################################################################################
+# for wae-initializer
+################################################################################
+
+
+SET(WAE_INITIALIZER_SOURCES
+    ${CMAKE_CURRENT_SOURCE_DIR}/wae_initializer.c
+)
+
+INCLUDE_DIRECTORIES(
+    ${PROJECT_SOURCE_DIR}/include
+    ${WEB_APP_ENC_DEPS_INCLUDE_DIRS}
+)
+
+# -fPIE and -pie flag is added for ASLR
+SET_SOURCE_FILES_PROPERTIES(
+    ${WAE_INITIALIZER_SOURCES}
+    PROPERTIES
+        COMPILE_FLAGS "-D_GNU_SOURCE -fvisibility=hidden -fPIE")
+
+ADD_EXECUTABLE(${TARGET_WAE_INITIALIZER} ${WAE_INITIALIZER_SOURCES})
+
+
+TARGET_LINK_LIBRARIES(${TARGET_WAE_INITIALIZER}
+    pthread
+    ${WEB_APP_ENC_DEPS_LIBRARIES}
+    ${TARGET_WEBAPPENC}
+    -pie
+)
+
+INSTALL(TARGETS ${TARGET_WAE_INITIALIZER}
+    DESTINATION ${BINDIR})
+
diff --git a/srcs/crypto_service.c b/srcs/crypto_service.c
new file mode 100644 (file)
index 0000000..eb1fc20
--- /dev/null
@@ -0,0 +1,372 @@
+/*
+ *  Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ *
+ * @file        crypto_service.c
+ * @author      Dongsun Lee (ds73.lee@samsung.com)
+ * @version     1.0
+ * @brief       provides encryption and decription operations.
+ */
+
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+#include <openssl/rsa.h>
+
+#include "web_app_enc.h"
+#include "wae_log.h"
+
+#define AES_256_KEY_SIZE 32
+
+#define WAE_FALSE 0
+#define WAE_TRUE  1
+
+static unsigned char AES_CBC_IV[16] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+                                        0x08, 0x39, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
+
+static int __initialized = WAE_FALSE;
+
+void _initialize()
+{
+    if(__initialized != WAE_TRUE) {
+        ERR_load_crypto_strings();
+        OpenSSL_add_all_algorithms();
+        __initialized = WAE_TRUE;
+    }
+}
+
+
+
+int encrypt_app_dek(const unsigned char* rsaPublicKey, size_t pubKeyLen,
+                    const unsigned char* dek, size_t dekLen,
+                    unsigned char** encryptedDek, size_t* encryptedDekLen)
+{
+    int ret = WAE_ERROR_NONE;
+    EVP_PKEY *pKey = NULL;
+    BIO* bio = NULL;
+    EVP_PKEY_CTX *ctx = NULL;
+    unsigned char* out = NULL;
+    size_t outLen = 0;
+
+    _initialize();
+
+    bio = BIO_new(BIO_s_mem());
+    BIO_write(bio, rsaPublicKey, pubKeyLen);
+    pKey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
+
+    if(pKey == NULL){
+        BIO_reset(bio);
+        BIO_write(bio, rsaPublicKey, pubKeyLen);
+        pKey = d2i_PUBKEY_bio(bio, NULL);
+    }
+
+    if(pKey == NULL) {
+        ret = WAE_ERROR_FILE;
+        WAE_SLOGE("Failt to convert to public key.");
+        goto error;
+    }
+
+    ctx = EVP_PKEY_CTX_new(pKey, NULL);
+    if(ctx == NULL) {
+        WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_CTX_new failed");
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+
+    if (EVP_PKEY_encrypt_init(ctx) <= 0) {
+        WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_encrypt_init failed");
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+    if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) {
+        WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_CTX_set_rsa_padding failed");
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+
+    /* Determine buffer length */
+    if (EVP_PKEY_encrypt(ctx, NULL, &outLen, dek, dekLen) <= 0) {
+        WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_encrypt failed");
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+
+    out = OPENSSL_malloc(outLen);
+    if(out == NULL) {
+        WAE_SLOGE("Encrypt APP DEK Failed. OPENSSL_malloc failed");
+        ret = WAE_ERROR_MEMORY;
+        goto error;
+    }
+
+    if (EVP_PKEY_encrypt(ctx, out, &outLen, dek, dekLen) <= 0) {
+        WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_encrypt failed");
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+
+    *encryptedDek = out;
+    *encryptedDekLen = outLen;
+
+error:
+    if(bio != NULL)
+        BIO_free(bio);
+    if(pKey != NULL)
+        EVP_PKEY_free(pKey);
+    if(ctx != NULL)
+        EVP_PKEY_CTX_free(ctx);
+    if(ret != WAE_ERROR_NONE && out != NULL)
+        OPENSSL_free(out);
+
+    return ret;
+}
+
+int decrypt_app_dek(const unsigned char* rsaPrivateKey, size_t priKeyLen,
+                    const char* priKeyPassword,
+                    const unsigned char* encryptedDek, size_t dencryptedDekLen,
+                    unsigned char** decryptedDek, size_t* decryptedDekLen)
+{
+    int ret = WAE_ERROR_NONE;
+    EVP_PKEY *pKey = NULL;
+    BIO* bio = NULL;
+    EVP_PKEY_CTX *ctx = NULL;
+    unsigned char* out = NULL;
+    size_t outLen = 0;
+
+    _initialize();
+
+    bio = BIO_new(BIO_s_mem());
+    BIO_write(bio, rsaPrivateKey, priKeyLen);
+    pKey = PEM_read_bio_PrivateKey(bio, NULL, NULL, (void *)priKeyPassword);
+
+    if(pKey == NULL) {
+        BIO_reset(bio);
+        BIO_write(bio, rsaPrivateKey, priKeyLen);
+        pKey = d2i_PrivateKey_bio(bio, NULL);
+    }
+
+    if(pKey == NULL) {
+        ret = WAE_ERROR_FILE;
+        WAE_SLOGE("Failt to convert to public key.");
+        goto error;
+    }
+
+    ctx = EVP_PKEY_CTX_new(pKey, NULL);
+    if(ctx == NULL) {
+        WAE_SLOGE("Decrypt APP DEK Failed. EVP_PKEY_CTX_new failed");
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+
+    if (EVP_PKEY_decrypt_init(ctx) <= 0) {
+        WAE_SLOGE("Decrypt APP DEK Failed. EVP_PKEY_decrypt_init failed");
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+    if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) {
+        WAE_SLOGE("Decrypt APP DEK Failed. EVP_PKEY_CTX_set_rsa_padding failed");
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+
+    /* Determine buffer length */
+    if (EVP_PKEY_decrypt(ctx, NULL, &outLen, encryptedDek, dencryptedDekLen) <= 0) {
+        WAE_SLOGE("Decrypt APP DEK Failed. EVP_PKEY_decrypt failed");
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+
+    out = OPENSSL_malloc(outLen);
+    if(out == NULL) {
+        WAE_SLOGE("Decrypt APP DEK Failed. OPENSSL_malloc failed");
+        ret = WAE_ERROR_MEMORY;
+        goto error;
+    }
+
+    if (EVP_PKEY_decrypt(ctx, out, &outLen, encryptedDek, dencryptedDekLen) <= 0) {
+        WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_decrypt failed");
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+
+    *decryptedDek = out;
+    *decryptedDekLen = outLen;
+
+error:
+    if(bio != NULL)
+        BIO_free(bio);
+    if(pKey != NULL)
+        EVP_PKEY_free(pKey);
+    if(ctx != NULL)
+        EVP_PKEY_CTX_free(ctx);
+    if(ret != WAE_ERROR_NONE && out != NULL)
+        OPENSSL_free(out);
+
+    return ret;
+}
+
+
+int encrypt_aes_cbc(const unsigned char* pKey, size_t keyLen,
+                    const unsigned char* pData, size_t dataLen,
+                    unsigned char** ppEncryptedData, size_t* pEncDataLen)
+{
+    EVP_CIPHER_CTX *ctx;
+    int len;
+    unsigned char *ciphertext = NULL;
+    size_t ciphertext_len;
+    unsigned char *iv = AES_CBC_IV;
+    int ret = WAE_ERROR_NONE;
+
+    _initialize();
+
+    WAE_SLOGI("Encryption Started. size=%d", dataLen);
+    /* check input paramter */
+    if( keyLen != 32 ) {
+        WAE_SLOGE("Encryption Failed. Invalid Key Length. keyLen=%d", keyLen);
+        return WAE_ERROR_INVALID_PARAMETER;
+    }
+
+    // assing a enough memory for decryption.
+    ciphertext = (unsigned char*) malloc(dataLen + 32);
+
+    /* Create and initialise the context */
+    if(!(ctx = EVP_CIPHER_CTX_new())) {
+        WAE_SLOGE("Encryption Failed. EVP_CIPHER_CTX_new failed");
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+
+    /* Initialise the encryption operation. IMPORTANT - ensure you use a key
+     * and IV size appropriate for your cipher
+     * In this example we are using 256 bit AES (i.e. a 256 bit key). The
+     * IV size for *most* modes is the same as the block size. For AES this
+     * is 128 bits */
+    if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, pKey, iv)) {
+        WAE_SLOGE("Encryption Failed. EVP_EncryptInit_ex failed");
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+
+    /* Provide the message to be encrypted, and obtain the encrypted output.
+     * EVP_EncryptUpdate can be called multiple times if necessary
+     */
+    if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, pData, dataLen)) {
+        WAE_SLOGE("Encryption Failed. EVP_EncryptUpdate failed");
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+    ciphertext_len = len;
+
+    /* Finalise the encryption. Further ciphertext bytes may be written at
+     * this stage.
+     */
+    if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) {
+        WAE_SLOGE("Encryption Failed. EVP_EncryptFinal_ex failed");
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+    ciphertext_len += len;
+
+    *ppEncryptedData = ciphertext;
+    *pEncDataLen = ciphertext_len;
+
+    ret = WAE_ERROR_NONE;
+    WAE_SLOGI("Encryption Ended Successfully. encrypted_len", ciphertext_len);
+error:
+    if(ctx != NULL)
+        EVP_CIPHER_CTX_free(ctx);
+    if(ret != WAE_ERROR_NONE && ciphertext != NULL)
+        free(ciphertext);
+    return ret;
+}
+
+int decrypt_aes_cbc(const unsigned char* pKey, size_t keyLen,
+                    const unsigned char* pData, size_t dataLen,
+                    unsigned char** ppDecryptedData, size_t* pDecDataLen)
+{
+    EVP_CIPHER_CTX *ctx;
+    int len;
+    unsigned char* plaintext = NULL;
+    size_t plaintext_len;
+    unsigned char *iv = AES_CBC_IV;
+    int ret = WAE_ERROR_NONE;
+
+    _initialize();
+
+    WAE_SLOGI("Decryption Started. size=%d", dataLen);
+
+    /* check input paramter */
+    if( keyLen != 32 ) {
+        WAE_SLOGE("Decryption Failed. Invalid Key Length. keyLen=%d", keyLen);
+        return WAE_ERROR_INVALID_PARAMETER;
+    }
+
+    // assing a enough memory for decryption.
+    plaintext = (unsigned char*) malloc(dataLen);
+
+    /* Create and initialise the context */
+    if(!(ctx = EVP_CIPHER_CTX_new())) {
+        WAE_SLOGE("Decryption Failed. EVP_CIPHER_CTX_new failed");
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+
+    /* Initialise the decryption operation. IMPORTANT - ensure you use a key
+     * and IV size appropriate for your cipher
+     * In this example we are using 256 bit AES (i.e. a 256 bit key). The
+     * IV size for *most* modes is the same as the block size. For AES this
+     * is 128 bits */
+    if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, pKey, iv)) {
+        WAE_SLOGE("Decryption Failed. EVP_DecryptInit_ex failed");
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+
+    /* Provide the message to be decrypted, and obtain the plaintext output.
+     * EVP_DecryptUpdate can be called multiple times if necessary
+     */
+    if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, pData, dataLen)) {
+        WAE_SLOGE("Decryption Failed. EVP_DecryptUpdate failed");
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+    plaintext_len = len;
+
+    /* Finalise the decryption. Further plaintext bytes may be written at
+     * this stage.
+     */
+    if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) {
+        WAE_SLOGE("Decryption Failed. EVP_DecryptFinal_ex failed");
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+    plaintext_len += len;
+
+    *ppDecryptedData = plaintext;
+    *pDecDataLen = plaintext_len;
+
+    ret = WAE_ERROR_NONE;
+    WAE_SLOGI("Decryption Ended Successfully. decrypted_len", plaintext_len);
+error:
+    if(ctx != NULL)
+        EVP_CIPHER_CTX_free(ctx);
+    if(ret != WAE_ERROR_NONE && plaintext != NULL)
+        free(plaintext);
+    return ret;
+}
+
diff --git a/srcs/crypto_service.h b/srcs/crypto_service.h
new file mode 100644 (file)
index 0000000..c49c34b
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ *  Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ *
+ * @file        crypto_service.h
+ * @author      Dongsun Lee (ds73.lee@samsung.com)
+ * @version     1.0
+ * @brief       a header for key manupulatation.
+ */
+
+
+
+#ifndef __TIZEN_CORE_WAE_CRYPTO_SERVICE_H
+#define __TIZEN_CORE_WAE_CRYPTO_SERVICE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stddef.h>
+
+
+int encrypt_app_dek(const unsigned char* rsaPublicKey, size_t pubKeyLen,
+                    const unsigned char* dek, const int dekLen,
+                    unsigned char** encryptedDek, size_t* encryptedDekLen);
+
+int decrypt_app_dek(const unsigned char* rsaPrivateKey, size_t priKeyLen,
+                    const char* priKeyPassword,
+                    const unsigned char* encryptedDek, size_t dencryptedDekLen,
+                    unsigned char** decryptedDek, size_t* decryptedDekLen);
+
+
+int encrypt_aes_cbc(const unsigned char* pKey, size_t keyLen,
+                    const unsigned char* pData, size_t dataLen,
+                    unsigned char** ppEncryptedData, size_t* pEncDataLen);
+
+int decrypt_aes_cbc(const unsigned char* pKey, size_t keyLen,
+                    const unsigned char* pData, size_t dataLen,
+                    unsigned char** ppDecryptedData, size_t* pDecDataLen);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __TIZEN_CORE_WAE_CRYPTO_SERVICE_H */
+
diff --git a/srcs/key_handler.c b/srcs/key_handler.c
new file mode 100644 (file)
index 0000000..4ec4e5c
--- /dev/null
@@ -0,0 +1,744 @@
+/*
+ *  Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  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        key_handler.c
+ * @author      Dongsun Lee (ds73.lee@samsung.com)
+ * @version     1.0
+ * @brief       a header for key manupulatation.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <ckmc/ckmc-manager.h>
+#include "wae_log.h"
+#include "web_app_enc.h"
+#include "key_handler.h"
+#include "crypto_service.h"
+
+#include <tzplatform_config.h>
+
+#define APP_DEK_KEK_PRIKEY_PASSWORD "wae_appdek_kek_1q2w3e4r"
+
+
+typedef struct _dek_cache_element{
+    char          pkgId[MAX_PKGID_LEN];
+    unsigned char dek[DEK_LEN];
+} dek_cache_element;
+
+dek_cache_element APP_DEK_CACHE[MAX_CACHE_SIZE];
+int NEXT_CACHE_IDX = -1;
+
+void _initialize_cache()
+{
+    NEXT_CACHE_IDX = 0;
+    memset(APP_DEK_CACHE, 0, sizeof(dek_cache_element)*MAX_CACHE_SIZE);
+}
+
+unsigned char* _get_app_dek_from_cache(const char* pkgId)
+{
+    int i = 0;
+
+    if(NEXT_CACHE_IDX < 0)
+        _initialize_cache();
+
+    for(i =0; i<MAX_CACHE_SIZE; i++) {
+        //WAE_SLOGI("CACHED APP_DEK[%d]=%s", i, APP_DEK_CACHE[i].pkgId);
+        if( strlen(APP_DEK_CACHE[i].pkgId) == strlen(pkgId) &&
+            strncmp(pkgId, APP_DEK_CACHE[i].pkgId, strlen(pkgId)) == 0) {
+            return APP_DEK_CACHE[i].dek;
+        }
+    }
+    return NULL;
+}
+
+void _add_app_dek_to_cache(const char* pkgId, unsigned char* dek)
+{
+    int i = 0;
+
+    if(NEXT_CACHE_IDX < 0)
+        _initialize_cache();
+
+    // if existing one has the same pkgid
+    for(i =0; i<MAX_CACHE_SIZE; i++) {
+        if( strlen(APP_DEK_CACHE[i].pkgId) == strlen(pkgId) &&
+            strncmp(pkgId, APP_DEK_CACHE[i].pkgId, strlen(pkgId)) == 0) {
+            memcpy(APP_DEK_CACHE[i].dek, dek, DEK_LEN);
+            return;
+        }
+    }
+
+    // for new pkgid
+    strncpy(APP_DEK_CACHE[NEXT_CACHE_IDX].pkgId, pkgId, strlen(pkgId));
+    memcpy(APP_DEK_CACHE[NEXT_CACHE_IDX].dek, dek, DEK_LEN);
+
+    NEXT_CACHE_IDX++;
+    if(NEXT_CACHE_IDX >= MAX_CACHE_SIZE)
+        NEXT_CACHE_IDX = 0;
+}
+
+void _remove_app_dek_from_cache(const char* pkgId)
+{
+    int i = 0;
+
+    for(i =0; i<MAX_CACHE_SIZE; i++) {
+        if( strlen(APP_DEK_CACHE[i].pkgId) == strlen(pkgId) &&
+            strncmp(pkgId, APP_DEK_CACHE[i].pkgId, strlen(pkgId)) == 0) {
+            memset(APP_DEK_CACHE[i].pkgId, 0, sizeof(APP_DEK_CACHE[i].pkgId));
+            return;
+        }
+    }
+
+}
+
+int _to_wae_error(int key_manager_error)
+{
+    switch(key_manager_error) {
+        case CKMC_ERROR_NONE:                return WAE_ERROR_NONE;
+        case CKMC_ERROR_INVALID_PARAMETER:   return WAE_ERROR_INVALID_PARAMETER;
+        case CKMC_ERROR_PERMISSION_DENIED:   return WAE_ERROR_PERMISSION_DENIED;
+        case CKMC_ERROR_DB_ALIAS_UNKNOWN:    return WAE_ERROR_NO_KEY;
+        case CKMC_ERROR_DB_ALIAS_EXISTS:     return WAE_ERROR_KEY_EXISTS;
+        default:                             return WAE_ERROR_KEY_MANAGER;
+    }
+}
+
+int _get_random(size_t length, unsigned char* random)
+{
+    FILE* f = NULL;
+    size_t i = 0;
+    int ch = 0;
+    //read random file
+    if((f = fopen(RANDOM_FILE, "r")) != NULL){
+        while( i < length){
+            if((ch = fgetc(f)) == EOF){
+                break;
+            }
+            random[i] = (unsigned char) ch;
+            i++;
+        }
+    }
+    if(f != NULL)
+        fclose(f);
+    return WAE_ERROR_NONE;
+}
+
+void _get_alias(const char* pPkgId, char* alias, size_t buff_len)
+{
+   snprintf(alias, buff_len, "%s%s%s%s",
+                            ckmc_label_shared_owner,
+                            ckmc_label_name_separator,
+                            APP_DEK_ALIAS_PFX,
+                            pPkgId);
+}
+
+void _get_dek_kek_alias(char* alias, size_t buff_len)
+{
+    snprintf(alias, buff_len, "%s%s%s",
+                            ckmc_label_shared_owner,
+                            ckmc_label_name_separator,
+                            APP_DEK_KEK_ALIAS);
+}
+
+void _get_dek_loading_done_alias(char* alias, size_t buff_len)
+{
+    snprintf(alias, buff_len, "%s%s%s",
+                            ckmc_label_shared_owner,
+                            ckmc_label_name_separator,
+                            APP_DEK_LOADING_DONE_ALIAS);
+}
+
+const char* _get_dek_kek_pub_key_path()
+{
+    return tzplatform_mkpath4(TZ_SYS_SHARE, "wae", "app_dek", "WAE_APPDEK_KEK_PublicKey.pem");
+}
+
+const char* _get_dek_kek_pri_key_path()
+{
+    return tzplatform_mkpath4(TZ_SYS_SHARE, "wae", "app_dek", "WAE_APPDEK_KEK_PrivateKey.pem");
+}
+
+const char* _get_dek_store_path()
+{
+    return tzplatform_mkpath3(TZ_SYS_SHARE, "wae", "app_dek");
+}
+
+int _add_dek_to_key_manager(const char* pPkgId, const unsigned char* pDek, size_t len)
+{
+    int ret = WAE_ERROR_NONE;
+    char alias[MAX_ALIAS_LEN] = {0,};
+    ckmc_raw_buffer_s buff;
+    ckmc_policy_s policy;
+
+    buff.data = (unsigned char *)pDek;
+    buff.size = len;
+
+    policy.password = NULL;
+    policy.extractable = true;
+
+    // save app_dek in key_manager
+    _get_alias(pPkgId, alias, sizeof(alias));
+
+    // even if it fails to remove, ignore it.
+    ret = _to_wae_error( ckmc_remove_alias(alias));
+
+    ret = _to_wae_error(ckmc_save_data(alias, buff, policy));
+    if(ret != WAE_ERROR_NONE) {
+        WAE_SLOGE("Fail to add APP_DEK to key-manager. pkgId=%s, ret=%d", pPkgId, ret);
+        goto error;
+    }
+
+    // share app_dek for web app laucher to use app_dek
+    ret = _to_wae_error(ckmc_set_permission(alias, pPkgId, CKMC_PERMISSION_READ));
+    if(ret != WAE_ERROR_NONE) {
+        WAE_SLOGE("Fail to set_permission to APP_DEK. pkgId=%s, ret=%d", pPkgId, ret);
+        goto error;
+    }
+    WAE_SLOGI("Success to add APP_DEK to key-manager. pkgId=%s", pPkgId);
+error:
+    return ret;
+}
+
+
+int _get_preloaded_app_dek_file_path(const char* pPkgId, char *path)
+{
+    sprintf(path, "%s/%s_%s.adek", _get_dek_store_path(), APP_DEK_FILE_PFX, pPkgId);
+    return WAE_ERROR_NONE;
+}
+
+int _extract_pkg_id_from_file_name(const char* fileName, char* pkgId)
+{
+    char* start = strstr(fileName, APP_DEK_FILE_PFX);
+    if(start == NULL){
+        WAE_SLOGE("Fail to extract pkgid from APP_DEK file. fileName=%s", fileName);
+        return WAE_ERROR_FILE;
+    }
+    start = start + strlen(APP_DEK_FILE_PFX) + 1;
+    char* end = strstr(fileName, ".adek");
+    if(start == NULL){
+        WAE_SLOGE("Fail to extract pkgid from APP_DEK file. fileName=%s", fileName);
+        return WAE_ERROR_FILE;
+    }
+    strncpy(pkgId, start, end-start);
+    pkgId[end-start] = 0;//terminate string
+    return WAE_ERROR_NONE;
+}
+
+int _read_encrypted_app_dek_from_file(const char* pPkgId, unsigned char** encrypted_app_dek, size_t *len)
+{
+    char path[MAX_PATH_LEN] = {0,};
+    _get_preloaded_app_dek_file_path(pPkgId, path);
+    return _read_from_file(path, encrypted_app_dek, len);
+}
+
+int _write_encrypted_app_dek_to_file(const char* pPkgId, const unsigned char* encrypted_app_dek, size_t len)
+{
+    char path[MAX_PATH_LEN] = {0,};
+    _get_preloaded_app_dek_file_path(pPkgId, path);
+    return _write_to_file( path, encrypted_app_dek, len);
+}
+
+int _read_from_file(const char* path, unsigned char** data, size_t* len)
+{
+    int ret = WAE_ERROR_NONE;
+    FILE* f = NULL;
+    int file_len = -1;
+    unsigned char* file_contents = NULL;
+    int ch = 0;
+    int i = 0;
+
+    f = fopen(path, "r");
+    if( f == NULL) {
+        WAE_SLOGE("Fail to open a file. file=%s", path);
+        ret = WAE_ERROR_FILE;
+        goto error;
+    }
+
+    fseek(f, 0, SEEK_END); // move to the end of a file
+    file_len = ftell(f);
+    fseek(f, 0, SEEK_SET); // move to the start of a file
+
+    file_contents = (unsigned char*) malloc(file_len);
+    if(file_contents == NULL) {
+         WAE_SLOGE("Fail to allocate memory for encrypted_app_dek");
+         ret = WAE_ERROR_MEMORY;
+         goto error;
+    }
+    memset(file_contents, 0x00, file_len);
+
+    while( (ch = fgetc(f)) != EOF) {
+        file_contents[i++]=(char)ch;
+    }
+
+    *data = file_contents;
+    *len = file_len;
+
+error:
+    if(f != NULL)
+        fclose(f);
+    if(ret != WAE_ERROR_NONE && file_contents != NULL)
+        free(file_contents);
+
+    return ret;
+}
+
+int _write_to_file(const char* path, const unsigned char* data, size_t len)
+{
+    int ret = WAE_ERROR_NONE;
+
+    FILE* f = NULL;
+    int write_len = -1;
+
+    f = fopen(path, "w");
+    if( f == NULL) {
+        WAE_SLOGE("Fail to open a file. file=%s", path);
+        ret = WAE_ERROR_FILE;
+        goto error;
+    }
+
+    write_len = fwrite(data, 1, len, f);
+    if(write_len != (int) len) {
+        WAE_SLOGE("Fail to write a file. file=%s", path);
+        ret = WAE_ERROR_FILE;
+        goto error;
+    }
+error:
+    if(f != NULL)
+        fclose(f);
+
+    return ret;
+}
+
+int get_app_dek(const char* pPkgId, unsigned char** ppDek, size_t* dekLen)
+{
+    int ret = WAE_ERROR_NONE;
+
+    char* password = NULL;
+    ckmc_raw_buffer_s *pDekBuffer = NULL;
+    char alias[MAX_ALIAS_LEN] = {0,};
+    unsigned char* pDek = NULL;
+    unsigned char* cached_dek = NULL;
+
+    // get dek from cache
+    cached_dek = _get_app_dek_from_cache(pPkgId);
+    if(cached_dek == NULL) {
+        // get APP_DEK from system database
+        _get_alias(pPkgId, alias, sizeof(alias));
+
+        ret = _to_wae_error(ckmc_get_data(alias, password, &pDekBuffer));
+        if(ret != WAE_ERROR_NONE) {
+            WAE_SLOGE("Fail to get APP_DEK from key-manager. alias=%s, ret=%d", alias, ret);
+            goto error;
+        }
+    }
+
+    pDek = (unsigned char*) malloc(DEK_LEN);
+    if(pDek == NULL) {
+        WAE_SLOGE("Fail to allocate a memory");
+        ret = WAE_ERROR_MEMORY;
+        goto error;
+    }
+    memcpy(pDek, (cached_dek != NULL) ? cached_dek : pDekBuffer->data, DEK_LEN);
+
+    *ppDek = pDek;
+    *dekLen = DEK_LEN;
+    WAE_SLOGI("Success to get APP_DEK from key-manager. pkgId=%s", pPkgId);
+error:
+    if(pDekBuffer != NULL)
+        ckmc_buffer_free(pDekBuffer);
+    if(ret != WAE_ERROR_NONE && pDek != NULL)
+        free(pDek);
+
+    return ret;
+}
+
+int create_app_dek(const char* pPkgId, unsigned char** ppDek, size_t* dekLen)
+{
+    int ret = WAE_ERROR_NONE;
+    unsigned char *dek= NULL;
+
+    dek = (unsigned char*) malloc(DEK_LEN);
+    if(dek  == NULL) {
+        ret = WAE_ERROR_MEMORY;
+        goto error;
+    }
+
+    ret = _get_random(DEK_LEN, dek);
+    if(ret != WAE_ERROR_NONE) {
+        WAE_SLOGE("Fail to get random for APP_DEK. pkgId=%s, ret=%d", pPkgId, ret);
+        goto error;
+    }
+
+    // save app_dek in key_manager
+    ret = _add_dek_to_key_manager(pPkgId, dek, DEK_LEN);
+    if(ret != WAE_ERROR_NONE) {
+        goto error;
+    }
+
+    // store APP_DEK in cache
+    _add_app_dek_to_cache(pPkgId, dek);
+
+    *ppDek = dek;
+    *dekLen = DEK_LEN;
+
+    WAE_SLOGI("Success to create APP_DEK and store it in key-manager. pkgId=%s", pPkgId);
+error:
+    if(ret != WAE_ERROR_NONE && dek != NULL)
+        free(dek);
+
+    return ret;
+}
+
+int get_preloaded_app_dek(const char* pPkgId, unsigned char** ppDek, size_t* dekLen)
+{
+    int ret = WAE_ERROR_NONE;
+    unsigned char* cached_dek= NULL;
+    unsigned char* dek = NULL;
+
+    // get dek from cache
+    cached_dek = _get_app_dek_from_cache(pPkgId);
+    if(cached_dek == NULL) {
+        WAE_SLOGE("Fail to get APP_DEK from cache for preloaded app");
+        ret = WAE_ERROR_NO_KEY;
+        goto error;
+    }
+
+    dek = (unsigned char*) malloc(DEK_LEN);
+    if(dek == NULL) {
+        WAE_SLOGE("Fail to allocate memory for preloaded app dek");
+        ret = WAE_ERROR_MEMORY;
+        goto error;
+    }
+    memcpy(dek, cached_dek, DEK_LEN);
+
+    *ppDek = dek;
+    *dekLen = DEK_LEN;
+error:
+    if(ret != WAE_ERROR_NONE && dek != NULL)
+        free(dek);
+
+    return ret;
+}
+
+int create_preloaded_app_dek(const char* pPkgId, unsigned char** ppDek, size_t* dekLen)
+{
+    int ret = WAE_ERROR_NONE;
+    unsigned char* dek = NULL;
+    unsigned char* encrypted_app_dek = NULL;
+    size_t encrypted_app_dek_len = 0;
+    unsigned char* pubKey = NULL;
+    size_t pubKeyLen = 0;
+
+    // create APP_DEK
+    dek = (unsigned char*) malloc(DEK_LEN);
+    if(dek == NULL) {
+        ret = WAE_ERROR_MEMORY;
+        goto error;
+    }
+
+    ret = _get_random(DEK_LEN, dek);
+    if(ret != WAE_ERROR_NONE) {
+        goto error;
+    }
+
+    // encrypt APP_DEK with APP_DEK_KEK
+    ret = _read_from_file(_get_dek_kek_pub_key_path(), &pubKey, &pubKeyLen);
+    if(ret != WAE_ERROR_NONE) {
+        WAE_SLOGE("Fail to read APP_DEK_KEK Public Key");
+        goto error;
+    }
+
+    ret = encrypt_app_dek(pubKey, pubKeyLen, dek, DEK_LEN, &encrypted_app_dek, &encrypted_app_dek_len);
+    if(ret != WAE_ERROR_NONE) {
+        WAE_SLOGE("Fail to encrypt APP_DEK with APP_DEK_KEK");
+        goto error;
+    }
+
+    // write APP_DEK in a file
+    ret = _write_encrypted_app_dek_to_file(pPkgId, encrypted_app_dek, encrypted_app_dek_len);
+    if(ret != WAE_ERROR_NONE) {
+        WAE_SLOGE("Fail to write encrypted APP_DEK. pkgId=%s", pPkgId);
+        goto error;
+    }
+
+    // store APP_DEK in cache
+    _add_app_dek_to_cache(pPkgId, dek);
+
+    *ppDek = dek;
+    *dekLen = DEK_LEN;
+    WAE_SLOGI("Success to create preleaded APP_DEK and write it in initail value file. pkgId=%s", pPkgId);
+
+error:
+    if(pubKey != NULL)
+        free(pubKey);
+    if(encrypted_app_dek != NULL)
+        free(encrypted_app_dek);
+    if(ret != WAE_ERROR_NONE && dek != NULL)
+        free(dek);
+    return ret;
+}
+
+
+int _get_app_dek_kek(unsigned char** ppDekKek, size_t* kekLen)
+{
+    int ret = WAE_ERROR_NONE;
+
+    ret = _read_from_file(_get_dek_kek_pri_key_path(), ppDekKek, kekLen);
+    if(ret != WAE_ERROR_NONE) {
+        WAE_SLOGE("Fail to read APP_DEK_KEK Private Key");
+        return ret;
+    }
+/*
+    char* password = NULL;
+    ckmc_raw_buffer_s *pKekBuffer = NULL;
+    unsigned char* pKek = NULL;
+
+    char dek_kek_alias[MAX_ALIAS_LEN] = {0, };
+    _get_dek_kek_alias(dek_kek_alias, sizeof(dek_kek_alias));
+
+    ret = _to_wae_error(ckmc_get_data(dek_kek_alias, password, &pKekBuffer));
+    if(ret != WAE_ERROR_NONE) {
+        WAE_SLOGE("Fail to get APP_DEK_KEK from key-manager. alias=%s, ret=%d", APP_DEK_KEK_ALIAS, ret);
+        goto error;
+    }
+
+    pKek = (unsigned char*) malloc(pKekBuffer->size);
+    if(pKek == NULL) {
+        WAE_SLOGE("Fail to allocate a memory");
+        ret = WAE_ERROR_MEMORY;
+        goto error;
+    }
+    memcpy(pKek, pKekBuffer->data, pKekBuffer->size);
+
+    *ppDekKek = pKek;
+    *kekLen = pKekBuffer->size;
+    WAE_SLOGI("Success to get APP_DEK_KEK from key-manager.");
+error:
+    if(pKekBuffer != NULL)
+        ckmc_buffer_free(pKekBuffer);
+    if(ret != WAE_ERROR_NONE && pKek != NULL)
+        free(pKek);
+*/
+    return ret;
+}
+
+
+int _get_app_deks_loaded()
+{
+    int ret = WAE_ERROR_NONE;
+
+    ckmc_raw_buffer_s *pBuffer = NULL;
+    char loading_done_alias[MAX_ALIAS_LEN] = {0, };
+
+    _get_dek_loading_done_alias(loading_done_alias, sizeof(loading_done_alias));
+
+    ret = _to_wae_error(ckmc_get_data(loading_done_alias, NULL, &pBuffer));
+    if(ret == WAE_ERROR_NO_KEY) {
+        WAE_SLOGI("APP_DEK_LOADING was not done");
+    } else if(ret == WAE_ERROR_NONE) {
+        WAE_SLOGI("APP_DEK_LOADING was already done");
+    } else {
+        WAE_SLOGE("Fail to get information from key-manager about APP_DEK_LOADING_DONE_ALIAS. ret=%d", ret);
+        goto error;
+    }
+
+error:
+    if(pBuffer != NULL)
+        ckmc_buffer_free(pBuffer);
+
+    return ret;
+}
+
+int _set_app_deks_loaded()
+{
+    int ret = WAE_ERROR_NONE;
+    ckmc_raw_buffer_s buff;
+    ckmc_policy_s policy;
+    unsigned char dummyData[1] =  {0};
+
+    buff.data = dummyData;
+    buff.size = sizeof(dummyData);
+
+    policy.password = NULL;
+    policy.extractable = true;
+
+    char loading_done_alias[MAX_ALIAS_LEN] = {0, };
+    _get_dek_loading_done_alias(loading_done_alias, sizeof(loading_done_alias));
+
+    ret = _to_wae_error(ckmc_save_data(loading_done_alias, buff, policy));
+    if(ret == WAE_ERROR_KEY_EXISTS) {
+        WAE_SLOGI("APP_DEK_LOADING was already done");
+        ret = WAE_ERROR_NONE;
+    } else if(ret != WAE_ERROR_NONE) {
+        WAE_SLOGE("Fail to set APP_DEK_LOADING_DONE_ALIAS to key-manager. ret=%d", ret);
+        goto error;
+    }
+
+    WAE_SLOGI("Success to set APP_DEK_LOADING_DONE_ALIAS to key-manager.");
+error:
+    return ret;
+}
+
+int _clear_app_deks_loaded()
+{
+    int ret = WAE_ERROR_NONE;
+    char loading_done_alias[MAX_ALIAS_LEN] = {0, };
+    _get_dek_loading_done_alias(loading_done_alias, sizeof(loading_done_alias));
+
+    ret = _to_wae_error(ckmc_remove_alias(loading_done_alias));
+    if(ret == WAE_ERROR_NO_KEY) {
+        WAE_SLOGI("APP_DEK_LOADING_DONE_ALIAS was not set to key-manager before.");
+        ret = WAE_ERROR_NONE;
+    }else if(ret != WAE_ERROR_NONE) {
+        WAE_SLOGE("Fail to clear APP_DEK_LOADING_DONE_ALIAS to key-manager. ret=%d", ret);
+    }
+
+    return ret;
+}
+
+int load_preloaded_app_deks(int reload)
+{
+    int ret = WAE_ERROR_NONE;
+
+    char pkgId[MAX_PKGID_LEN] = {0, };
+
+    DIR *dir = NULL;
+    struct dirent entry;
+    struct dirent *result;
+    int error;
+    char file_path_buff[MAX_PATH_LEN];
+    unsigned char* encrypted_app_dek = NULL;
+    size_t encrypted_app_dek_len = 0;
+    unsigned char* app_dek = NULL;
+    size_t app_dek_len = 0;
+    unsigned char* priKey = NULL;
+    size_t priKeyLen = 0;
+
+    int error_during_loading = 0;
+
+    if(reload != WAE_TRUE) {
+        // check if all deks were already loaded into key-manager.
+        ret = _get_app_deks_loaded();
+        if(ret == WAE_ERROR_NONE) {
+            return ret;
+        }
+    }
+
+    ret = _get_app_dek_kek(&priKey, &priKeyLen);
+    if(ret != WAE_ERROR_NONE) {
+        WAE_SLOGE("Fail to get APP_DEK_KEK Private Key");
+        return ret;
+    }
+
+    dir = opendir(_get_dek_store_path());
+    if(dir == NULL) {
+        WAE_SLOGE("Fail to open dir. dir=%s", _get_dek_store_path());
+        ret = WAE_ERROR_FILE;
+        goto error;
+    }
+
+    for(;;) {
+        error = readdir_r(dir, &entry, &result);
+        if( error != 0 ) {
+            ret = WAE_ERROR_FILE;
+            goto error;
+        }
+        // readdir_r returns NULL in *result if the end
+        // of the directory stream is reached
+        if(result == NULL)
+            break;
+
+        // regular file && start with KEY_MANAGER_INITIAL_VALUE_FILE_PFX
+        if(entry.d_type == DT_REG && strstr(entry.d_name, APP_DEK_FILE_PFX) != NULL) {
+            memset(file_path_buff, 0, sizeof(file_path_buff));
+            sprintf(file_path_buff, "%s/%s", _get_dek_store_path(), entry.d_name);
+
+            ret = _extract_pkg_id_from_file_name(entry.d_name, pkgId);
+            if(ret != WAE_ERROR_NONE) {
+                WAE_SLOGW("Fail to extract pkgid from file. It will be ignored. file=%s",file_path_buff);
+                continue;
+            }
+
+            ret = _read_from_file(file_path_buff, &encrypted_app_dek, &encrypted_app_dek_len);
+            if(ret != WAE_ERROR_NONE || encrypted_app_dek == NULL) {
+                error_during_loading++;
+                WAE_SLOGW("Fail to read file. It will be ignored. file=%s",file_path_buff);
+                continue;
+            }
+
+            ret = decrypt_app_dek(priKey, priKeyLen, APP_DEK_KEK_PRIKEY_PASSWORD,
+                                  encrypted_app_dek, encrypted_app_dek_len,
+                                  &app_dek, &app_dek_len);
+            if(ret != WAE_ERROR_NONE || app_dek == NULL) {
+                error_during_loading++;
+                WAE_SLOGW("Fail to decrypt APP DEK. It will be ignored. file=%s",file_path_buff);
+                continue;
+            }
+
+            // save app_dek in key_manager
+            ret = _add_dek_to_key_manager(pkgId, app_dek, app_dek_len);
+            // free temp objects
+            free(app_dek);
+            free(encrypted_app_dek);
+            app_dek = NULL;
+            encrypted_app_dek = NULL;
+
+            if(ret == WAE_ERROR_KEY_EXISTS) {
+                WAE_SLOGI("Key Manager already has APP_DEK. It will be ignored. file=%s",file_path_buff);
+                continue;
+            }else if(ret != WAE_ERROR_NONE) {
+                error_during_loading++;
+                WAE_SLOGW("Fail to add APP DEK to key-manager. file=%s",file_path_buff);
+                continue;
+            }
+        }
+    }
+
+    ret = _set_app_deks_loaded();
+    if(ret == WAE_ERROR_NONE) {
+        WAE_SLOGI("Success to load_preloaded_app_deks");
+        ret = WAE_ERROR_NONE;
+    }else {
+        WAE_SLOGW("Fail to _set_app_deks_loaded to key-manager. ret=%d", ret);
+    }
+error:
+    if(priKey != NULL)
+        free(priKey);
+
+    return ret;
+}
+
+
+int remove_app_dek(const char* pPkgId)
+{
+    int ret = CKMC_ERROR_NONE;
+    char alias[MAX_ALIAS_LEN] = {0,};
+
+    _get_alias(pPkgId, alias,sizeof(alias));
+
+    ret = _to_wae_error(ckmc_remove_alias(alias));
+    if(ret != WAE_ERROR_NONE) {
+        WAE_SLOGE("Fail to remove APP_DEK from  key-manager. pkgId=%s, alias=%s, ret=%d", pPkgId, alias, ret);
+        goto error;
+    }
+
+    _remove_app_dek_from_cache(pPkgId);
+    WAE_SLOGI("Success to remove APP_DEK from  key-manager. pkgId=%s", pPkgId);
+error:
+    return WAE_ERROR_NONE;
+}
diff --git a/srcs/key_handler.h b/srcs/key_handler.h
new file mode 100644 (file)
index 0000000..c855241
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ *  Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  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        key_handler.h
+ * @author      Dongsun Lee (ds73.lee@samsung.com)
+ * @version     1.0
+ * @brief       a header for key manupulatation.
+ */
+
+
+
+#ifndef __TIZEN_CORE_WAE_KEY_HANDLER_H
+#define __TIZEN_CORE_WAE_KEY_HANDLER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stddef.h>
+
+#define APP_DEK_ALIAS_PFX "APP_DEK_"
+#define APP_DEK_LOADING_DONE_ALIAS "APP_DEKS_LOADING_FINISHED"
+
+#define DEK_LEN 32
+#define MAX_ALIAS_LEN 256
+#define MAX_PKGID_LEN 256
+#define MAX_PATH_LEN  512
+#define MAX_CACHE_SIZE 100
+
+
+#define RANDOM_FILE        "/dev/urandom"
+#define APP_DEK_FILE_PFX   "WAE_APP_DEK"
+#define APP_DEK_KEK_ALIAS  "WAE_APP_DEK_KEK"
+
+#define WAE_TRUE  1
+#define WAE_FALSE 0
+
+void _initialize_cache();
+unsigned char* _get_app_dek_from_cache(const char* pkgId);
+void _add_app_dek_to_cache(const char* pkgId, unsigned char* dek);
+void _remove_app_dek_from_cache(const char* pkgId);
+int _get_random(size_t length, unsigned char* random);
+void _get_alias(const char* pPkgId, char* alias, size_t buff_len);
+void _get_dek_kek_alias(char* alias, size_t buff_len);
+void _get_dek_loading_done_alias(char* alias, size_t buff_len);
+const char* _get_dek_kek_pub_key_path();
+const char* _get_dek_kek_pri_key_path();
+const char* _get_dek_store_path();
+int _add_dek_to_key_manager(const char* pPkgId, const unsigned char* pDek, size_t len);
+int _get_preloaded_app_dek_file_path(const char* pPkgId, char *path);
+int _extract_pkg_id_from_file_name(const char* fileName, char* pkgId);
+int _read_encrypted_app_dek_from_file(const char* pPkgId, unsigned char** encrypted_app_dek, size_t*len);
+int _write_encrypted_app_dek_to_file(const char* pPkgId, const unsigned char* encrypted_app_dek, size_t len);
+int _read_from_file(const char* path, unsigned char** data, size_t* len);
+int _write_to_file(const char* path, const unsigned char* data, size_t len);
+int _get_app_dek_kek_from_key_manager(unsigned char** ppDekKek, size_t* kekLen);
+int _get_app_deks_loaded();
+int _set_app_deks_loaded();
+int _clear_app_deks_loaded();
+
+int get_app_dek(const char* pPkgId, unsigned char** ppDek, size_t *dekLen);
+int create_app_dek(const char* pPkgId, unsigned char** ppDek, size_t *dekLen);
+int get_preloaded_app_dek(const char* pPkgId, unsigned char** ppDek, size_t* dekLen);
+int create_preloaded_app_dek(const char* pPkgId, unsigned char** ppDek, size_t *dekLen);
+int load_preloaded_app_deks(int reload);
+int remove_app_dek(const char* pPkgId);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __TIZEN_CORE_WAE_KEY_HANDLER_H */
+
diff --git a/srcs/wae_initializer.c b/srcs/wae_initializer.c
new file mode 100644 (file)
index 0000000..011c8a0
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ *  Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  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        wae_initializer.c
+ * @author      Dongsun Lee (ds73.lee@samsung.com)
+ * @version     1.0
+ * @brief       tool for importing APP DEKs during booting
+ */
+
+#include "key_handler.h"
+#include "web_app_enc.h"
+#include "wae_log.h"
+#include <stdio.h>
+
+int main(int argc, char* argv[])
+{
+    int ret = WAE_ERROR_NONE;
+    int reload = WAE_FALSE;
+
+    if(argc == 2 && strcmp(argv[1], "--reload")==0) {
+        reload = WAE_TRUE;
+    }
+
+    ret = load_preloaded_app_deks(reload);
+    if(ret == WAE_ERROR_NONE) {
+        printf("WAE INITIALIZER was finished successfully.\n");
+        WAE_SLOGI("WAE INITIALIZER was finished successfully.");
+        return 0;
+    }else {
+        printf("WAE INITIALIZER was finished with error. ret=%d\n", ret);
+        WAE_SLOGE("WAE INITIALIZER was finished with error. ret=%d", ret);
+        return -1;
+    }
+}
diff --git a/srcs/wae_log.h b/srcs/wae_log.h
new file mode 100644 (file)
index 0000000..6dfe44a
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ *  Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  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        wae_log.h
+ * @author      Dongsun Lee (ds73.lee@samsung.com)
+ * @version     1.0
+ * @brief       a header for loggin.
+ */
+
+#ifndef __WAE_LOG_H__
+#define __WAE_LOG_H__
+
+/* Use DLOG logging mechanism */
+#include <dlog.h>
+
+#define TAG_WAE           "WAE"
+
+#define WAE_SLOGD(format, arg...) SLOG(LOG_DEBUG, TAG_WAE, format, ##arg)
+#define WAE_SLOGI(format, arg...) SLOG(LOG_INFO,  TAG_WAE, format, ##arg)
+#define WAE_SLOGW(format, arg...) SLOG(LOG_WARN,  TAG_WAE, format, ##arg)
+#define WAE_SLOGE(format, arg...) SLOG(LOG_ERROR, TAG_WAE, format, ##arg)
+#define WAE_SLOGF(format, arg...) SLOG(LOG_FATAL, TAG_WAE, format, ##arg)
+
+#endif /* __WAE_LOG_H__*/
+
diff --git a/srcs/web_app_enc.c b/srcs/web_app_enc.c
new file mode 100644 (file)
index 0000000..7bc8484
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ *  Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  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        web_app_enc.c
+ * @author      Dongsun Lee (ds73.lee@samsung.com)
+ * @version     1.0
+ * @brief       provides fucntions for encryption and decryption of web application.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "web_app_enc.h"
+#include "key_handler.h"
+#include "crypto_service.h"
+#include "wae_log.h"
+
+
+int _wae_encrypt_downloaded_web_application(const char* pPkgId,
+                                const unsigned char* pData, size_t dataLen,
+                                unsigned char** ppEncryptedData, size_t* pEncDataLen)
+{
+    int ret = WAE_ERROR_NONE;
+    unsigned char *pDek = NULL;
+    size_t dekLen = -1;
+
+    if(pPkgId == NULL) {
+        WAE_SLOGE("Invalid Parameter. pPkgId is NULL");
+        ret = WAE_ERROR_INVALID_PARAMETER;
+        goto error;
+    }
+    if(pData == NULL || dataLen <= 0) {
+        WAE_SLOGE("Invalid Parameter. pData is NULL or invalid dataLen(%d)", dataLen);
+        ret = WAE_ERROR_INVALID_PARAMETER;
+        goto error;
+    }
+    if(ppEncryptedData == NULL || pEncDataLen == NULL) {
+        WAE_SLOGE("Invalid Parameter. ppEncryptedData or pEncDataLen is NULL");
+        ret = WAE_ERROR_INVALID_PARAMETER;
+        goto error;
+    }
+
+    // get APP_DEK.
+    //   if not exists, create APP_DEK
+    ret = get_app_dek(pPkgId, &pDek, &dekLen);
+    if(ret == WAE_ERROR_NO_KEY) {
+        ret = create_app_dek(pPkgId, &pDek, &dekLen);
+    }
+    if(ret != WAE_ERROR_NONE) {
+        goto error;
+    }
+
+    // encrypt
+    ret = encrypt_aes_cbc(pDek, dekLen, pData, dataLen, ppEncryptedData, pEncDataLen);
+    if(ret != WAE_ERROR_NONE) {
+        goto error;
+    }
+
+error:
+    if(pDek != NULL)
+        free(pDek);
+
+    return ret;
+}
+
+int _wae_decrypt_downloaded_web_application(const char* pPkgId,
+                                const unsigned char* pData, size_t dataLen,
+                                unsigned char** ppDecryptedData, size_t* pDecDataLen)
+{
+    int ret = WAE_ERROR_NONE;
+    unsigned char *pDek = NULL;
+    size_t dekLen = -1;
+
+    if(pPkgId == NULL) {
+        WAE_SLOGE("Invalid Parameter. pPkgId is NULL");
+        ret = WAE_ERROR_INVALID_PARAMETER;
+        goto error;
+    }
+    if(pData == NULL || dataLen <= 0) {
+        WAE_SLOGE("Invalid Parameter. pData is NULL or invalid dataLen(%d)", dataLen);
+        ret = WAE_ERROR_INVALID_PARAMETER;
+        goto error;
+    }
+    if(ppDecryptedData == NULL || pDecDataLen == NULL) {
+        WAE_SLOGE("Invalid Parameter. ppDecryptedData or pDecDataLen is NULL");
+        ret = WAE_ERROR_INVALID_PARAMETER;
+        goto error;
+    }
+
+    ret = get_app_dek(pPkgId, &pDek, &dekLen);
+    if(ret != WAE_ERROR_NONE) {
+        goto error;
+    }
+
+    // decrypt
+    ret = decrypt_aes_cbc(pDek, dekLen, pData, dataLen, ppDecryptedData, pDecDataLen);
+    if(ret != WAE_ERROR_NONE) {
+        goto error;
+    }
+
+error:
+    if(pDek != NULL)
+        free(pDek);
+
+    return ret;
+}
+
+int _wae_encrypt_preloaded_web_application(const char* pPkgId,
+                                const unsigned char* pData, size_t dataLen,
+                                unsigned char** ppEncryptedData, size_t* pEncDataLen)
+{
+
+    int ret = WAE_ERROR_NONE;
+    unsigned char *pDek = NULL;
+    size_t dekLen = -1;
+
+    if(pPkgId == NULL) {
+        WAE_SLOGE("Invalid Parameter. pPkgId is NULL");
+        ret = WAE_ERROR_INVALID_PARAMETER;
+        goto error;
+    }
+    if(pData == NULL || dataLen <= 0) {
+        WAE_SLOGE("Invalid Parameter. pData is NULL or invalid dataLen(%d)", dataLen);
+        ret = WAE_ERROR_INVALID_PARAMETER;
+        goto error;
+    }
+    if(ppEncryptedData == NULL || pEncDataLen == NULL) {
+        WAE_SLOGE("Invalid Parameter. ppEncryptedData or pEncDataLen is NULL");
+        ret = WAE_ERROR_INVALID_PARAMETER;
+        goto error;
+    }
+
+    ret = get_preloaded_app_dek(pPkgId, &pDek, &dekLen);
+    if(ret == WAE_ERROR_NO_KEY) {
+        ret = create_preloaded_app_dek(pPkgId, &pDek, &dekLen);
+    }
+    if(ret != WAE_ERROR_NONE) {
+        goto error;
+    }
+
+    // encrypt
+    ret = encrypt_aes_cbc(pDek, dekLen, pData, dataLen, ppEncryptedData, pEncDataLen);
+    if(ret != WAE_ERROR_NONE) {
+        goto error;
+    }
+error:
+    if(pDek != NULL)
+        free(pDek);
+
+    return ret;
+}
+
+int _wae_decrypt_preloaded_web_application(const char* pPkgId,
+                                const unsigned char* pData, size_t dataLen,
+                                unsigned char** ppDecryptedData, size_t* pDecDataLen)
+{
+    // same with the decryption of downloaded web application
+    return _wae_decrypt_downloaded_web_application(pPkgId, pData, dataLen, ppDecryptedData, pDecDataLen);
+}
+
+int wae_encrypt_web_application(const char* pPkgId,int isPreloaded,
+                                const unsigned char* pData, size_t dataLen,
+                                unsigned char** ppEncryptedData, size_t* pEncDataLen)
+{
+    int ret = WAE_ERROR_NONE;
+
+    if(isPreloaded)
+        ret = _wae_encrypt_preloaded_web_application(pPkgId, pData, dataLen, ppEncryptedData, pEncDataLen);
+    else
+        ret = _wae_encrypt_downloaded_web_application(pPkgId, pData, dataLen, ppEncryptedData, pEncDataLen);
+
+    WAE_SLOGI("Encrypt Web App. pkgId=%s, isPreloaded=%d, dataLen=%d, ret=%d",
+               pPkgId, isPreloaded, dataLen, ret);
+    return ret;
+}
+
+int wae_decrypt_web_application(const char* pPkgId, int isPreloaded,
+                                const unsigned char* pData, size_t dataLen,
+                                unsigned char** ppDecryptedData, size_t* pDecDataLen)
+{
+    int ret = WAE_ERROR_NONE;
+
+    if(isPreloaded)
+        ret = _wae_decrypt_preloaded_web_application(pPkgId, pData, dataLen, ppDecryptedData, pDecDataLen);
+    else
+        ret =_wae_decrypt_downloaded_web_application(pPkgId, pData, dataLen, ppDecryptedData, pDecDataLen);
+
+    WAE_SLOGI("Decrypt Web App. pkgId=%s, isPreloaded=%d, dataLen=%d, ret=%d",
+               pPkgId, isPreloaded, dataLen, ret);
+    return ret;
+}
+
+
+int wae_remove_app_dek(const char* pPkgId)
+{
+    int ret = WAE_ERROR_NONE;
+    ret = remove_app_dek(pPkgId);
+    WAE_SLOGI("Remove APP DEK. pkgId=%s, ret=%d", pPkgId, ret);
+    return ret;
+}
diff --git a/systemd/CMakeLists.txt b/systemd/CMakeLists.txt
new file mode 100644 (file)
index 0000000..bf7bb79
--- /dev/null
@@ -0,0 +1,8 @@
+CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/systemd/webappenc-initializer.service.in
+               ${CMAKE_SOURCE_DIR}/systemd/webappenc-initializer.service @ONLY)
+
+INSTALL(FILES
+    ${CMAKE_SOURCE_DIR}/systemd/webappenc-initializer.service
+    DESTINATION
+    ${SYSTEMD_UNIT_DIR}
+)
diff --git a/systemd/webappenc-initializer.service.in b/systemd/webappenc-initializer.service.in
new file mode 100644 (file)
index 0000000..e9441d8
--- /dev/null
@@ -0,0 +1,12 @@
+[Unit]
+Description=Import APP DEKs for Preloaded Web App Decryption
+DefaultDependencies=no
+Requires=central-key-manager.service
+After=central-key-manager.service
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/wae_initializer
+
+[Install]
+WantedBy=multi-user.target
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e1d0d6d
--- /dev/null
@@ -0,0 +1,37 @@
+################################################################################
+# for wae_tests
+################################################################################
+
+
+SET(WEB_APP_ENC_TEST_SOURCES
+    ${CMAKE_CURRENT_SOURCE_DIR}/wae_tests.c
+)
+
+INCLUDE_DIRECTORIES(
+    ${WEB_APP_ENC_DEPS_INCLUDE_DIRS}
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${PROJECT_SOURCE_DIR}/include
+    ${PROJECT_SOURCE_DIR}/srcs
+)
+
+ADD_EXECUTABLE(${TARGET_WEBAPPENC_TEST} ${WEB_APP_ENC_TEST_SOURCES})
+
+
+TARGET_LINK_LIBRARIES(${TARGET_WEBAPPENC_TEST}
+    ${WEB_APP_ENC_DEPS_LIBRARIES}
+    ${TARGET_WEBAPPENC}
+)
+
+
+INSTALL(TARGETS ${TARGET_WEBAPPENC_TEST}
+    DESTINATION ${BINDIR}
+    PERMISSIONS OWNER_READ
+    OWNER_WRITE
+    OWNER_EXECUTE
+    GROUP_READ
+    GROUP_EXECUTE
+    WORLD_READ
+    WORLD_EXECUTE
+)
+
+
diff --git a/tests/wae_tests.c b/tests/wae_tests.c
new file mode 100644 (file)
index 0000000..49b6b32
--- /dev/null
@@ -0,0 +1,815 @@
+/*
+ *  Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  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        wae_tests.c
+ * @author      Dongsun Lee (ds73.lee@samsung.com)
+ * @version     1.0
+ * @brief       internal test cases for libwebappenc.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "web_app_enc.h"
+#include "key_handler.h"
+#include "crypto_service.h"
+
+#include <tzplatform_config.h>
+
+static size_t tc_seq = 0;
+static size_t tc_succ = 0;
+static size_t tc_fail = 0;
+
+#define FPRINTF(format, args...) fprintf(stdout, format, ##args)
+
+static int RUNTC(int (*tc_method)(), const char* tc_name)
+{
+    int ret = WAE_ERROR_NONE;
+    FPRINTF("[%02d:%s]started...\n", tc_seq, tc_name);
+    ret = tc_method();
+    if(ret == WAE_ERROR_NONE) {
+        FPRINTF("[%02d:%s]ended. SUCCESS\n\n", tc_seq, tc_name);
+        tc_succ++;
+    } else {
+        FPRINTF("[%02d:%s]ended. FAIL. error=%d\n\n", tc_seq, tc_name, ret);
+        tc_fail++;
+    }
+    tc_seq++;
+    return ret;
+}
+
+static void PRINT_TC_SUMMARY()
+{
+    FPRINTF("\n");
+    FPRINTF("===============================================\n");
+    FPRINTF(" TOTAL = %d, SUCCESS = %d, FAIL = %d\n", tc_seq, tc_succ, tc_fail);
+    FPRINTF("===============================================\n");
+}
+
+void _print_binary_to_hex(const char* msg, unsigned char* bin, size_t len)
+{
+    size_t i = 0;
+    FPRINTF("%s", msg);
+    for(i=0; i<len; i++) {
+        FPRINTF("%02x", bin[i]);
+    }
+    FPRINTF("\n");
+}
+
+int _compare_binary(const unsigned char* b1, size_t b1Len, const unsigned char* b2, size_t b2Len)
+{
+    size_t i = 0;
+    if(b1Len != b2Len)
+        return b1Len - b2Len;
+    for(i=0; i<b1Len; i++) {
+        if(b1[i] != b2[i])
+            return b1[i] - b2[i];
+    }
+    return 0;
+}
+
+
+//=================================================================================
+// tests for crypto_service.h
+//=================================================================================
+int wae_tc_encrypt_decrypt_app_dek()
+{
+    int ret = WAE_ERROR_NONE;
+    unsigned char dek[32];
+    unsigned char* encryptedDek = NULL;
+    size_t encryptedDekLen = 0;
+    unsigned char* decryptedDek = NULL;
+    size_t decryptedDekLen = 0;
+
+    const char* priKey =
+            "-----BEGIN RSA PRIVATE KEY-----\n"
+            "MIIEpgIBAAKCAQEA0kWtjpRO7Zh2KX2naVE/BDJdrfwK9xexfNA0MkY2VJ4J2AKM\n"
+            "YTj1D1jntceryupCEHOvP3rum+WsFvPXduz9+VKnSsSqj4jcTUubtpDUGA5G79Iq\n"
+            "LEPFuSBaqI8Uwkzd08pE+s30oaJDnNazMhSq8JkqBPoCCwtUs73ruE9VbtsBO/kT\n"
+            "lASIAfe8nXqcJLcDQgWYhizjJw0Pi6d74oCwS2OTvQDNvsXfFnA0ZJEEYw/rZLir\n"
+            "j7OHoOjz+Sh5N+1uA3Up6SPPEbHuP6L12YxqHdy7gnJXodLhvE/cR4SN9VW7+qmC\n"
+            "MBjmLkBejGrEX3STS9sLI7MZHu9Y26dwuYb4+wIDAQABAoIBAQCwxqV/vc2RUGDe\n"
+            "xuXM0+IvrAw37jJlw4SS0xNexMp+XxMViCbuwYy851h96azS/himbiuCKd6aL/96\n"
+            "mGunbtyiFEvSvv5Jh5z2Wr9BQAcfZjla+4w7BIsg9UNifE/OfgLsQBu34xhsHtfK\n"
+            "7nFehCOl/I5n+qtnD5KZPe0DWacQdwY4vEAj6YyXdb2bBg+MiwE9KVxGEIUDbklh\n"
+            "Is70JXczjLZCS+lIpOKh0/lbZmBZePoUbVTtS+GvtPTpQC/aTHRkwGoEtuPEWpbL\n"
+            "0Q1d6zO+vDJVLJlb5FF2haghs8IlqAxkkPjeUTNye+WktRrDQxmPu/blbxQrygfq\n"
+            "Au5tBnsxAoGBAOiVtcpg32puo3Yq2Y78oboe9PuHaQP0d3DhwP3/7J0BeNslpjW7\n"
+            "E1LWsVsCanxTE8XPUdFfAWgMk7lQqESN0wawGmSmWk+eQPZdjHanBaC8vh7aKjo6\n"
+            "q9FdT1DKjrRi23QyDco3f3E7hvM93IAAhw1ikNu8DT19JAxtdeMh5WAZAoGBAOdw\n"
+            "6neEvIFXh3RWEv2/GKVhVR8mxDqxmuFdXpOF+YWsK0Tg4uC8jm9kUGnwXgT2Mjke\n"
+            "oAwYAFcRbHQQGsxy/vkV16kv4aurTE2hMpjeXCAakwV0Pi2w1f9WnDokjgORkOmc\n"
+            "+QK9I8egdFPMVDfQjhLslhSUY0Eb4qcJ6q9WxfQzAoGBANSsAFybk+7oWAO3TtQW\n"
+            "YXOk1vIgcYAyS/0mEKixGZS/QdlxZbf/5b17nxTO8rvX416fIftG2ixgQ7vR6us0\n"
+            "m9+jq56ZFj9zP4eHJudf9h9yNo5TgwVXnMCGh/4iGbcMJgrrsfxUHu5VNiK5UCSj\n"
+            "VtqAZGDoZVryUMIkXQVhezIRAoGBAN7QUIqcGbcUA24257Wu4hVlrUN+WPCAyDEr\n"
+            "aL/x/ZV5eXaoYwQlw6LuGpTDOmDgfN2M5FyARuOL/LOIRaSLGXnIU4WoeUSCd8VM\n"
+            "6Z9Og7bMnrpjfPEUDBH02hcH1kkNPUwLOZgva2Dm0tdSIcpSWFVTu/E4Io4uQHi8\n"
+            "DVqc2ZsNAoGBAJT76ezXNSSv8hnrKqTpwgTicpqhRZ3eFQjyl4HRL26AJMKv++x8\n"
+            "4/IsVIwxaHzpbN3nnCjmAHV4gX9YpxVnvYcZflC9WZeDkwNMLmPYb3Zg27EzSMfQ\n"
+            "8yrfWJZo3qobipcHf1yohAt4fHk9kUKtPHEwp0xKe//rfhswLb3VCzvQ\n"
+            "-----END RSA PRIVATE KEY-----";
+    const char* pubKey =
+            "-----BEGIN PUBLIC KEY-----\n"
+            "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0kWtjpRO7Zh2KX2naVE/\n"
+            "BDJdrfwK9xexfNA0MkY2VJ4J2AKMYTj1D1jntceryupCEHOvP3rum+WsFvPXduz9\n"
+            "+VKnSsSqj4jcTUubtpDUGA5G79IqLEPFuSBaqI8Uwkzd08pE+s30oaJDnNazMhSq\n"
+            "8JkqBPoCCwtUs73ruE9VbtsBO/kTlASIAfe8nXqcJLcDQgWYhizjJw0Pi6d74oCw\n"
+            "S2OTvQDNvsXfFnA0ZJEEYw/rZLirj7OHoOjz+Sh5N+1uA3Up6SPPEbHuP6L12Yxq\n"
+            "Hdy7gnJXodLhvE/cR4SN9VW7+qmCMBjmLkBejGrEX3STS9sLI7MZHu9Y26dwuYb4\n"
+            "+wIDAQAB\n"
+            "-----END PUBLIC KEY-----";
+
+    ret = encrypt_app_dek((const unsigned char*) pubKey, strlen(pubKey),
+                          dek, sizeof(dek), &encryptedDek, &encryptedDekLen);
+    if(ret != WAE_ERROR_NONE){
+        FPRINTF("...FAIL: encrypt_app_dek. ret=%d\n", ret);
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+
+    ret = decrypt_app_dek((const unsigned char*) priKey, strlen(priKey), NULL,
+                          encryptedDek, encryptedDekLen, &decryptedDek, &decryptedDekLen);
+    if(ret != WAE_ERROR_NONE){
+        FPRINTF("...FAIL: decrypt_app_dek. ret=%d\n", ret);
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+
+    _print_binary_to_hex("...ORIG DEK= ", dek, sizeof(dek));
+    _print_binary_to_hex("...ENC  DEK= ", encryptedDek, encryptedDekLen);
+    _print_binary_to_hex("...DEC  DEK= ", decryptedDek, decryptedDekLen);
+
+    if(_compare_binary(dek, sizeof(dek), decryptedDek, decryptedDekLen) != 0) {
+        FPRINTF("...FAIL: ORIG DEK != decrypted DEK\n");
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+
+    ret = WAE_ERROR_NONE;
+
+error:
+    if(encryptedDek != NULL)
+        free(encryptedDek);
+    if(decryptedDek != NULL)
+        free(decryptedDek);
+
+    return ret;
+}
+
+int wae_tc_encrypt_decrypt_aes_cbc()
+{
+    int ret = WAE_ERROR_NONE;
+
+    unsigned char dek[32] = {0, };
+    size_t keyLen = 32;
+    const char* plaintext= "adbdfdfdfdfdererfdfdfererfdrerfdrer";
+    size_t plaintextLen = strlen(plaintext);
+    unsigned char* encrypted = NULL;
+    size_t encLen = 0;
+    unsigned char* decrypted = NULL;
+    size_t decLen = 0;
+    char decrypted_str[1024] = {0, };
+
+    ret = _get_random(keyLen, dek);
+
+    ret = encrypt_aes_cbc(dek, keyLen, (const unsigned char*)plaintext, plaintextLen, &encrypted, &encLen);
+    if(ret != WAE_ERROR_NONE){
+        FPRINTF("...FAIL: encrypt_aes_cbc. ret=%d\n", ret);
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+
+    ret = decrypt_aes_cbc(dek, keyLen, encrypted, encLen, &decrypted, &decLen);
+    if(ret != WAE_ERROR_NONE){
+        FPRINTF("...FAIL: decrypt_aes_cbc. ret=%d\n", ret);
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+
+    if(plaintextLen != decLen) {
+        FPRINTF("...FAIL: plaintextLen(%d) != decLen(%d)\n", plaintextLen, decLen);
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+
+    memcpy(decrypted_str, decrypted, decLen);
+    FPRINTF("...plaintext = %s\n", plaintext);
+    FPRINTF("...decrypted = %s\n", decrypted_str);
+    if(strcmp(plaintext, decrypted_str) != 0) {
+        FPRINTF("...FAIL: plaintext(%s) != decrypted(%s)\n", plaintext, decrypted_str);
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+
+error:
+    if(encrypted != NULL)
+        free(encrypted);
+    if(decrypted != NULL)
+        free(decrypted);
+
+    return ret;
+}
+
+//=================================================================================
+// tests for key_handler.h
+//=================================================================================
+int wae_tc_cache()
+{
+    int ret = WAE_ERROR_NONE;
+
+    const char* pkg1 = "pkg1";
+    const char* pkg2 = "pkg2";
+    const char* pkg3 = "pkg3";
+    const char* pkgDummy = "dummy";
+
+    unsigned char dek1[32] = {1, };
+    unsigned char dek2[32] = {2, };
+    unsigned char dek3[32] = {3, };
+    unsigned char* retDek = NULL;
+
+    _initialize_cache();
+
+    _add_app_dek_to_cache(pkg1, dek1);
+    _add_app_dek_to_cache(pkg2, dek2);
+    _add_app_dek_to_cache(pkg3, dek3);
+
+    retDek = NULL;
+    retDek = _get_app_dek_from_cache(pkg1);
+    if(retDek == NULL || _compare_binary(dek1, 32, retDek, 32) != 0) {
+        FPRINTF("failed in cache. Diffent DEK1\n");
+        ret = WAE_ERROR_UNKNOWN;
+        goto error;
+    }
+    _print_binary_to_hex("...DEK1         : ", dek1, 32);
+    _print_binary_to_hex("...Returen DEK1 : ", retDek, 32);
+
+    retDek = NULL;
+    retDek = _get_app_dek_from_cache(pkg2);
+    if(retDek == NULL || _compare_binary(dek2, 32, retDek, 32) != 0) {
+        FPRINTF("failed in cache. Diffent DEK2\n");
+        ret = WAE_ERROR_UNKNOWN;
+        goto error;
+    }
+    _print_binary_to_hex("...DEK2         : ", dek2, 32);
+    _print_binary_to_hex("...Returen DEK1 : ", retDek, 32);
+
+    retDek = NULL;
+    retDek = _get_app_dek_from_cache(pkg3);
+    if(retDek == NULL || _compare_binary(dek3, 32, retDek, 32) != 0) {
+        FPRINTF("failed in cache. Diffent DEK3\n");
+        ret = WAE_ERROR_UNKNOWN;
+        goto error;
+    }
+    _print_binary_to_hex("...DEK3         : ", dek3, 32);
+    _print_binary_to_hex("...Returen DEK3 : ", retDek, 32);
+
+    retDek = NULL;
+    retDek = _get_app_dek_from_cache(pkgDummy);
+    if(retDek != NULL) {
+        FPRINTF("failed in cache. Wrong DEK_DUMMY1 returned\n");
+        _print_binary_to_hex("retured wrong DEK : ", retDek, 32);
+        ret = WAE_ERROR_UNKNOWN;
+        goto error;
+    }
+
+    _remove_app_dek_from_cache(pkg3);
+    retDek = NULL;
+    retDek = _get_app_dek_from_cache(pkg3);
+    if(retDek != NULL) {
+        FPRINTF("fail to remove app dek from cache\n");
+        ret = WAE_ERROR_UNKNOWN;
+        goto error;
+    }
+
+    _initialize_cache();
+
+    _add_app_dek_to_cache(pkg1, dek1);
+
+    retDek = NULL;
+    retDek = _get_app_dek_from_cache(pkg2);
+    if(retDek != NULL) {
+        FPRINTF("failed in cache. Wrong DEK_DUMMY2 returned\n");
+        _print_binary_to_hex("retured wrong DEK : ", retDek, 32);
+        ret = WAE_ERROR_UNKNOWN;
+        goto error;
+    }
+
+    ret = WAE_ERROR_NONE;
+error:
+    return ret;
+}
+
+int wae_tc_get_random()
+{
+    int ret = WAE_ERROR_NONE;
+
+    size_t rand_len = 32;
+    unsigned char random[32] = {0, };
+
+    ret = _get_random(rand_len, random);
+
+    _print_binary_to_hex("...RANDOM = ", random, sizeof(random));
+
+    return ret;
+}
+
+int wae_tc_get_alias()
+{
+    int ret = WAE_ERROR_NONE;
+
+    const char* pkgId = "TEST_PKG_ID";
+    char sys_alias[256] = {0, };
+
+    _get_alias(pkgId, sys_alias, sizeof(sys_alias));
+
+    FPRINTF("...pkgid=%s, system alias=%s\n", pkgId, sys_alias);
+
+    return ret;
+}
+
+int wae_tc_add_get_remove_dek()
+{
+    int ret = WAE_ERROR_NONE;
+
+    const char* pkgId = "TEST_PKG_ID";
+
+    size_t dekLen= 32;
+    unsigned char dek[32] = {0, };
+    size_t storedDekLen = 0;
+    unsigned char* storedDek = NULL;
+
+    ret = _get_random(dekLen, dek);
+
+    remove_app_dek(pkgId);
+
+    ret = _add_dek_to_key_manager(pkgId, dek, dekLen);
+    if(ret != WAE_ERROR_NONE) {
+        FPRINTF("...FAIL: _add_dek_to_key_manager. ret=%d\n", ret);
+        goto error;
+    }
+
+    ret = get_app_dek(pkgId, &storedDek, &storedDekLen);
+    if(ret != WAE_ERROR_NONE) {
+        FPRINTF("...FAIL: get_app_dek. ret=%d\n", ret);
+        goto error;
+    }
+
+    if(_compare_binary(dek, dekLen, storedDek, storedDekLen) != 0 ) {
+        ret = WAE_ERROR_KEY_MANAGER;
+        FPRINTF("...FAIL: DEK != STORED_DEK.\n");
+        goto error;
+    }
+
+    ret = remove_app_dek(pkgId);
+    if(ret != WAE_ERROR_NONE) {
+        FPRINTF("...FAIL: remove_app_dek. ret=%d\n", ret);
+        goto error;
+    }
+
+    ret = get_app_dek(pkgId, &storedDek, &storedDekLen);
+    if(ret == WAE_ERROR_NONE) {
+        ret = WAE_ERROR_UNKNOWN;
+        FPRINTF("...FAIL: APP DEK still exists in key_manager.\n");
+        goto error;
+    }
+
+    ret = WAE_ERROR_NONE;
+error:
+    if(storedDek != NULL)
+        free(storedDek);
+
+    return ret;
+}
+
+int wae_tc_get_preloaded_app_dek_file_path()
+{
+    int ret = WAE_ERROR_NONE;
+
+    const char *pkgId = "test_pkg";
+    const char *expectedPath = tzplatform_mkpath4(TZ_SYS_SHARE,
+                                    "wae", "app_dek", "WAE_APP_DEK_test_pkg.adek");
+    char path[100];
+
+    ret = _get_preloaded_app_dek_file_path(pkgId, path);
+    FPRINTF("...expected path : %s\n", expectedPath);
+    FPRINTF("...returned path : %s\n", path);
+
+    if(ret != WAE_ERROR_NONE || strncmp(expectedPath, path, strlen(expectedPath)) != 0) {
+        ret = WAE_ERROR_UNKNOWN;
+        goto error;
+    }
+error:
+    return ret;
+}
+
+int wae_tc_extract_pkg_id_from_file_name()
+{
+    int ret = WAE_ERROR_NONE;
+    const char* fileName = "WAE_APP_DEK_test_pkg.adek";
+    const char* expectedPkgId = "test_pkg";
+    char pkgId[100];
+
+    ret = _extract_pkg_id_from_file_name(fileName, pkgId);
+    FPRINTF("...expected pkgId: %s\n", expectedPkgId);
+    FPRINTF("...returned pkgId: %s\n", pkgId);
+
+    if(ret != WAE_ERROR_NONE || strncmp(expectedPkgId, pkgId, strlen(expectedPkgId)) != 0) {
+        ret = WAE_ERROR_UNKNOWN;
+        goto error;
+    }
+error:
+    return ret;
+
+}
+
+int wae_tc_read_write_encrypted_app_dek()
+{
+    int ret = WAE_ERROR_NONE;
+    const char* pkgId = "write_test_pkg";
+    unsigned char dek[256];
+    unsigned char* readDek = NULL;
+    size_t readDekLen = 0;
+
+    ret = _write_encrypted_app_dek_to_file(pkgId, dek, sizeof(dek));
+    if(ret != WAE_ERROR_NONE) {
+        FPRINTF("Fail to _write_encrypted_app_dek_to_file. pkgId=%s\n", pkgId);
+        goto error;
+    }
+
+    ret = _read_encrypted_app_dek_from_file(pkgId, &readDek, &readDekLen);
+    if(ret != WAE_ERROR_NONE) {
+        FPRINTF("Fail to _read_encrypted_app_dek_from_file. pkgId=%s\n", pkgId);
+        goto error;
+    }
+
+    _print_binary_to_hex("...ORIG DEK= ", dek, sizeof(dek));
+    _print_binary_to_hex("...READ DEK= ", readDek, readDekLen);
+    if(_compare_binary(dek, sizeof(dek), readDek, readDekLen) != 0 ) {
+        ret = WAE_ERROR_UNKNOWN;
+        FPRINTF("...FAIL: DEK != read_DEK.\n");
+        goto error;
+    }
+
+error:
+    if(readDek != NULL)
+        free(readDek);
+    return ret;
+}
+
+
+int wae_tc_create_app_dek()
+{
+    int ret = WAE_ERROR_NONE;
+
+    const char* pkgId = "TEST_PKG_ID";
+    unsigned char* dek = NULL;
+    size_t dekLen = 0;
+
+    size_t storedDekLen = 0;
+    unsigned char* storedDek = NULL;
+
+    remove_app_dek(pkgId);
+
+    ret = create_app_dek(pkgId, &dek, &dekLen);
+    if(ret != WAE_ERROR_NONE) {
+        FPRINTF("...FAIL: create_app_dek. ret=%d\n", ret);
+        goto error;
+    }
+
+    ret = get_app_dek(pkgId, &storedDek, &storedDekLen);
+    if(ret != WAE_ERROR_NONE) {
+        ret = WAE_ERROR_KEY_MANAGER;
+        FPRINTF("...FAIL: get_app_dek. ret=%d\n", ret);
+        goto error;
+    }
+
+    _print_binary_to_hex("...CREATED  DEK = ", dek, dekLen);
+    _print_binary_to_hex("...STORED   DEK = ", storedDek, storedDekLen);
+    if(_compare_binary(dek, dekLen, storedDek, storedDekLen) != 0 ) {
+        ret = WAE_ERROR_FILE;
+        FPRINTF("...FAIL: DEK != STORED_DEK.\n");
+        goto error;
+    }
+
+    remove_app_dek(pkgId);
+
+    ret = WAE_ERROR_NONE;
+error:
+    if(dek != NULL)
+        free(dek);
+    if(storedDek != NULL)
+        free(storedDek);
+    return ret;
+}
+
+int wae_tc_get_create_preloaded_app_dek()
+{
+    int ret = WAE_ERROR_NONE;
+
+    const char* pkgId = "TEST_PKG_ID_FOR_CREATE";
+    unsigned char *dek = NULL;
+    unsigned char *readDek = NULL;
+    size_t readDekLen = 0;
+    size_t dekLen = 0;
+
+    ret = get_preloaded_app_dek(pkgId, &readDek, &readDekLen);
+    if(ret != WAE_ERROR_NO_KEY) {
+        FPRINTF("...FAIL: There should be no APP DEK.  get_preloaded_app_dek. ret=%d\n", ret);
+        ret = WAE_ERROR_FILE;
+        goto error;
+    }
+
+    ret = create_preloaded_app_dek(pkgId, &dek, &dekLen);
+    if(ret != WAE_ERROR_NONE) {
+        FPRINTF("...FAIL: create_preloaded_app_dek. ret=%d\n", ret);
+        goto error;
+    }
+
+    ret = get_preloaded_app_dek(pkgId, &readDek, &readDekLen);
+    if(ret != WAE_ERROR_NONE) {
+        FPRINTF("...FAIL: get_preloaded_app_dek. ret=%d\n", ret);
+        goto error;
+    }
+
+    _print_binary_to_hex("...CREATED DEK = ", dek, dekLen);
+    _print_binary_to_hex("...READ    DEK = ", readDek, readDekLen);
+
+    if(_compare_binary(dek, dekLen, readDek, readDekLen) != 0 ) {
+        ret = WAE_ERROR_FILE;
+        FPRINTF("...FAIL: DEK != READ_DEK.\n");
+        goto error;
+    }
+
+    ret = WAE_ERROR_NONE;
+error:
+    if(dek != NULL)
+        free(dek);
+    if(readDek != NULL)
+        free(readDek);
+    return ret;
+}
+
+int wae_tc_load_preloaded_app_deks()
+{
+    int ret = WAE_ERROR_NONE;
+
+    const char* pkgId1 = "TEST_PKGID_1";
+    unsigned char* dek1 = NULL;
+    size_t dekLen1 = 0;
+    unsigned char* readDek1 = NULL;
+    size_t readDekLen1 = 0;
+    char path1[MAX_PATH_LEN] = {0, };
+    FILE *f1 = NULL;
+
+    const char* pkgId2 = "TEST_PKGID_2";
+    unsigned char* dek2 = NULL;
+    size_t dekLen2 = 0;
+    unsigned char* readDek2 = NULL;
+    size_t readDekLen2 = 0;
+    char path2[MAX_PATH_LEN] = {0, };
+    FILE *f2 = NULL;
+
+    _get_preloaded_app_dek_file_path(pkgId1, path1);
+    _get_preloaded_app_dek_file_path(pkgId2, path2);
+
+    // remove old test data
+    remove_app_dek(pkgId1);
+    remove_app_dek(pkgId2);
+    unlink(path1);
+    unlink(path2);
+
+    // create 2 dek for preloaded app
+    ret = create_preloaded_app_dek(pkgId1, &dek1, &dekLen1);
+    if(ret != WAE_ERROR_NONE) {
+        FPRINTF("...FAIL: create_preloaded_app_dek. ret=%d\n", ret);
+        goto error;
+    }
+
+    ret = create_preloaded_app_dek(pkgId2, &dek2, &dekLen2);
+    if(ret != WAE_ERROR_NONE) {
+        FPRINTF("...FAIL: create_preloaded_app_dek. ret=%d\n", ret);
+        goto error;
+    }
+
+    // load_preloaded_app_deks
+    ret = load_preloaded_app_deks(WAE_TRUE);
+    if(ret != WAE_ERROR_NONE) {
+        FPRINTF("...FAIL: load_preloaded_app_deks. ret=%d\n", ret);
+        goto error;
+    }
+
+    // get_app_dek
+    ret = get_app_dek(pkgId1, &readDek1, &readDekLen1);
+    if(ret != WAE_ERROR_NONE) {
+        FPRINTF("...FAIL: get_app_dek. ret=%d\n", ret);
+        goto error;
+    }
+
+    ret = get_app_dek(pkgId2, &readDek2, &readDekLen2);
+    if(ret != WAE_ERROR_NONE) {
+        FPRINTF("...FAIL: get_app_dek. ret=%d\n", ret);
+        goto error;
+    }
+
+    _print_binary_to_hex("...CREATED DEK1 = ", dek1, dekLen1);
+    _print_binary_to_hex("...READ    DEK1 = ", readDek1, readDekLen1);
+    if(_compare_binary(dek1, dekLen1, readDek1, readDekLen1) != 0 ) {
+        ret = WAE_ERROR_FILE;
+        FPRINTF("...FAIL: DEK1 != READ_DEK1.\n");
+        goto error;
+    }
+
+    _print_binary_to_hex("...CREATED DEK2 = ", dek2, dekLen2);
+    _print_binary_to_hex("...READ    DEK2 = ", readDek2, readDekLen2);
+    if(_compare_binary(dek2, dekLen2, readDek2, readDekLen2) != 0 ) {
+        ret = WAE_ERROR_FILE;
+        FPRINTF("...FAIL: DEK2 != READ_DEK2.\n");
+        goto error;
+    }
+
+    // remove_app_dek
+    remove_app_dek(pkgId1);
+    remove_app_dek(pkgId2);
+
+    ret = WAE_ERROR_NONE;
+error:
+    if(dek1 != NULL)
+        free(dek1);
+    if(readDek1 != NULL)
+        free(readDek1);
+    if(f1 != NULL)
+        fclose(f1);
+    if(dek2 != NULL)
+        free(dek2);
+    if(readDek2 != NULL)
+        free(readDek2);
+    if(f2 != NULL)
+        fclose(f2);
+
+    return ret;
+}
+
+
+int wae_tc_encrypt_decrypt_web_application()
+{
+    int ret = WAE_ERROR_NONE;
+
+    const char* pkgId1 = "testpkg_for_downloaded";
+    const char* pkgId2 = "testpkg_for_preloaded";
+    const char* plaintext= "adbdfdfdfdfdererfdfdfererfdrerfdrer";
+    size_t plaintextLen = strlen(plaintext);
+    unsigned char* encrypted = NULL;
+    size_t encLen = 0;
+    unsigned char* decrypted = NULL;
+    size_t decLen = 0;
+    char decrypted_str[1024] = {0, };
+
+    int isPreloaded = 0; // Downloaded
+
+    // remove old test data
+    ret = wae_remove_app_dek(pkgId1);
+    ret = wae_remove_app_dek(pkgId2);
+    ret = _clear_app_deks_loaded();
+
+    // test for downloaded web application
+    ret = wae_encrypt_web_application(pkgId1, isPreloaded,
+                                      (const unsigned char*)plaintext, plaintextLen,
+                                      &encrypted, &encLen);
+    if(ret != WAE_ERROR_NONE){
+        FPRINTF("...FAIL: wae_encrypt_web_application. ret=%d\n", ret);
+        goto error;
+    }
+
+    _remove_app_dek_from_cache(pkgId1);
+
+    ret = wae_decrypt_web_application(pkgId1, isPreloaded, encrypted, encLen, &decrypted, &decLen);
+    if(ret != WAE_ERROR_NONE){
+        FPRINTF("...FAIL: wae_decrypt_web_application. ret=%d\n", ret);
+        goto error;
+    }
+
+    if(plaintextLen != decLen) {
+        FPRINTF("...FAIL: plaintextLen(%d) != decLen(%d)\n", plaintextLen, decLen);
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+
+    memcpy(decrypted_str, decrypted, decLen);
+    FPRINTF("...plaintext(downloaded) = %s\n", plaintext);
+    FPRINTF("...decrypted(downloaded) = %s\n", decrypted_str);
+    if(strcmp(plaintext, decrypted_str) != 0) {
+        FPRINTF("...FAIL: plaintext(%s) != decrypted(%s)\n", plaintext, decrypted_str);
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+
+    ret = wae_remove_app_dek(pkgId1);
+    if(ret != WAE_ERROR_NONE){
+        FPRINTF("...FAIL: wae_remove_app_dek. ret=%d\n", ret);
+        goto error;
+    }
+
+
+    // test for preloaded web application
+    isPreloaded = 1;
+
+    ret = wae_encrypt_web_application(pkgId2, isPreloaded,
+                                      (const unsigned char*)plaintext, plaintextLen,
+                                      &encrypted, &encLen);
+    if(ret != WAE_ERROR_NONE){
+        FPRINTF("...FAIL: wae_encrypt_web_application. ret=%d\n", ret);
+        goto error;
+    }
+    // encrypt test twice
+    ret = wae_encrypt_web_application(pkgId2, isPreloaded,
+                                      (const unsigned char*)plaintext, plaintextLen,
+                                      &encrypted, &encLen);
+    if(ret != WAE_ERROR_NONE){
+        FPRINTF("...FAIL: wae_encrypt_web_application2. ret=%d\n", ret);
+        goto error;
+    }
+
+    ret = wae_decrypt_web_application(pkgId2, isPreloaded, encrypted, encLen, &decrypted, &decLen);
+    if(ret != WAE_ERROR_NONE){
+        FPRINTF("...FAIL: wae_decrypt_web_application. ret=%d\n", ret);
+        goto error;
+    }
+
+    _remove_app_dek_from_cache(pkgId2);
+
+    if(plaintextLen != decLen) {
+        FPRINTF("...FAIL: plaintextLen(%d) != decLen(%d)\n", plaintextLen, decLen);
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+
+    memcpy(decrypted_str, decrypted, decLen);
+    FPRINTF("...plaintext(preloaded) = %s\n", plaintext);
+    FPRINTF("...decrypted(preloaded) = %s\n", decrypted_str);
+    if(strcmp(plaintext, decrypted_str) != 0) {
+        FPRINTF("...FAIL: plaintext(%s) != decrypted(%s)\n", plaintext, decrypted_str);
+        ret = WAE_ERROR_CRYPTO;
+        goto error;
+    }
+
+    ret = wae_remove_app_dek(pkgId2);
+    if(ret != WAE_ERROR_NONE){
+        FPRINTF("...FAIL: wae_remove_app_dek. ret=%d\n", ret);
+        goto error;
+    }
+
+error:
+    if(encrypted != NULL)
+        free(encrypted);
+    if(decrypted != NULL)
+        free(decrypted);
+
+    return ret;
+}
+
+
+int run_test_cases()
+{
+    RUNTC(wae_tc_encrypt_decrypt_app_dek, "wae_tc_encrypt_decrypt_app_dek");
+    RUNTC(wae_tc_encrypt_decrypt_aes_cbc, "wae_tc_encrypt_decrypt_aes_cbc");
+    RUNTC(wae_tc_cache, "wae_tc_cache");
+
+    RUNTC(wae_tc_get_random, "wae_tc_get_random");
+    RUNTC(wae_tc_get_alias, "wae_tc_get_alias");
+    RUNTC(wae_tc_add_get_remove_dek, "wae_tc_add_get_remove_dek");
+    RUNTC(wae_tc_get_preloaded_app_dek_file_path, "wae_tc_get_preloaded_app_dek_file_path");
+    RUNTC(wae_tc_extract_pkg_id_from_file_name, "wae_tc_extract_pkg_id_from_file_name");
+    RUNTC(wae_tc_read_write_encrypted_app_dek, "wae_tc_read_write_encrypted_app_dek");
+    RUNTC(wae_tc_create_app_dek, "wae_tc_create_app_dek");
+    RUNTC(wae_tc_get_create_preloaded_app_dek, "wae_tc_get_create_preloaded_app_dek");
+    RUNTC(wae_tc_load_preloaded_app_deks, "wae_tc_load_preloaded_app_deks");
+    RUNTC(wae_tc_encrypt_decrypt_web_application, "wae_tc_encrypt_decrypt_web_application");
+
+    PRINT_TC_SUMMARY();
+    return 0;
+}
+
+int main(void)
+{
+    int ret = 0;
+
+    ret = run_test_cases();
+
+    return ret;
+}