summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDongsun Lee <ds73.lee@samsung.com>2015-05-26 00:42:38 (GMT)
committerDongsun Lee <ds73.lee@samsung.com>2015-07-24 01:58:41 (GMT)
commit7abaa019637e0a534969d304cae7f7f43c4ab0a6 (patch)
tree9a2bb4f95b6c50ac39394abf87022d4a1a95fef2
parentd6556f8d8b13aadc9907b6609b773e29d2e22e7a (diff)
downloadlibwebappenc-7abaa019637e0a534969d304cae7f7f43c4ab0a6.zip
libwebappenc-7abaa019637e0a534969d304cae7f7f43c4ab0a6.tar.gz
libwebappenc-7abaa019637e0a534969d304cae7f7f43c4ab0a6.tar.bz2
Change-Id: Ibb7891bee67bdd82f34187f5da2fc3c4bbfa8fcd Signed-off-by: Dongsun Lee <ds73.lee@samsung.com>
-rw-r--r--AUTHORS1
-rw-r--r--CMakeLists.txt93
-rw-r--r--LICENSE.Apache-2.0203
-rw-r--r--build/CMakeLists.txt25
-rw-r--r--build/libwebappenc.pc.in11
-rw-r--r--include/CMakeLists.txt4
-rw-r--r--include/web_app_enc.h120
-rw-r--r--packaging/libwebappenc.manifest8
-rw-r--r--packaging/libwebappenc.spec115
-rw-r--r--resources/CMakeLists.txt12
-rw-r--r--resources/README_APP_DEK1
-rw-r--r--resources/WAE_APPDEK_KEK_PrivateKey.pem30
-rw-r--r--resources/WAE_APPDEK_KEK_PublicKey.pem9
-rw-r--r--srcs/CMakeLists.txt67
-rw-r--r--srcs/crypto_service.c372
-rw-r--r--srcs/crypto_service.h57
-rw-r--r--srcs/key_handler.c744
-rw-r--r--srcs/key_handler.h86
-rw-r--r--srcs/wae_initializer.c47
-rw-r--r--srcs/wae_log.h38
-rw-r--r--srcs/web_app_enc.c213
-rw-r--r--systemd/CMakeLists.txt8
-rw-r--r--systemd/webappenc-initializer.service.in12
-rw-r--r--tests/CMakeLists.txt37
-rw-r--r--tests/wae_tests.c815
25 files changed, 3128 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
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
index 0000000..c9fec0e
--- /dev/null
+++ b/CMakeLists.txt
@@ -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
index 0000000..247c97d
--- /dev/null
+++ b/LICENSE.Apache-2.0
@@ -0,0 +1,203 @@
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt
new file mode 100644
index 0000000..338e7ce
--- /dev/null
+++ b/build/CMakeLists.txt
@@ -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
index 0000000..2af6c92
--- /dev/null
+++ b/build/libwebappenc.pc.in
@@ -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
index 0000000..26e801c
--- /dev/null
+++ b/include/CMakeLists.txt
@@ -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
index 0000000..2e31a3c
--- /dev/null
+++ b/include/web_app_enc.h
@@ -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
index 0000000..226aaa0
--- /dev/null
+++ b/packaging/libwebappenc.manifest
@@ -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
index 0000000..b3c2cbc
--- /dev/null
+++ b/packaging/libwebappenc.spec
@@ -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
index 0000000..4462cee
--- /dev/null
+++ b/resources/CMakeLists.txt
@@ -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
index 0000000..724b8c2
--- /dev/null
+++ b/resources/README_APP_DEK
@@ -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
index 0000000..e27950c
--- /dev/null
+++ b/resources/WAE_APPDEK_KEK_PrivateKey.pem
@@ -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
index 0000000..f0dfcea
--- /dev/null
+++ b/resources/WAE_APPDEK_KEK_PublicKey.pem
@@ -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
index 0000000..e94a7d4
--- /dev/null
+++ b/srcs/CMakeLists.txt
@@ -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
index 0000000..eb1fc20
--- /dev/null
+++ b/srcs/crypto_service.c
@@ -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
index 0000000..c49c34b
--- /dev/null
+++ b/srcs/crypto_service.h
@@ -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
index 0000000..4ec4e5c
--- /dev/null
+++ b/srcs/key_handler.c
@@ -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
index 0000000..c855241
--- /dev/null
+++ b/srcs/key_handler.h
@@ -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
index 0000000..011c8a0
--- /dev/null
+++ b/srcs/wae_initializer.c
@@ -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
index 0000000..6dfe44a
--- /dev/null
+++ b/srcs/wae_log.h
@@ -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
index 0000000..7bc8484
--- /dev/null
+++ b/srcs/web_app_enc.c
@@ -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
index 0000000..bf7bb79
--- /dev/null
+++ b/systemd/CMakeLists.txt
@@ -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
index 0000000..e9441d8
--- /dev/null
+++ b/systemd/webappenc-initializer.service.in
@@ -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
index 0000000..e1d0d6d
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -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
index 0000000..49b6b32
--- /dev/null
+++ b/tests/wae_tests.c
@@ -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;
+}