Remove reload option to wae initializer service 55/103255/3
authorKyungwook Tak <k.tak@samsung.com>
Wed, 7 Dec 2016 08:22:40 +0000 (17:22 +0900)
committerKyungwook Tak <k.tak@samsung.com>
Thu, 8 Dec 2016 06:09:41 +0000 (15:09 +0900)
Reload option is not needed anymore.
To be secure, remove all KEKs from dek store (also adek) after loading
preloaded adeks once. Loaded adeks are stored in key-manager so they're
useless.
Related test cases are added. (load preloaded app deks)

(TODO) To use key-manager initial value feature is highly considered
to store KEK private key more securely.

Change-Id: I2f6c645398277968cd7d480236d1802a07fa33df
Signed-off-by: Kyungwook Tak <k.tak@samsung.com>
12 files changed:
packaging/libwebappenc.spec
srcs/key_handler.c
srcs/key_handler.h
srcs/key_manager.c
srcs/wae_initializer.c
tests/CMakeLists.txt
tests/internals.cpp
tests/resources/CMakeLists.txt [new file with mode: 0644]
tests/resources/prikey.pem [new file with mode: 0644]
tests/resources/pubkey.pem [new file with mode: 0644]
tests/test-helper.cpp
tests/test-helper.h

index 760f3e2..4184b84 100644 (file)
@@ -117,3 +117,4 @@ fi
 %license LICENSE.BSL-1.0
 %{bin_dir}/wae_tests
 %{_libdir}/libwae_tests_common.so*
+%attr(660, %user_name, %group_name) %{rw_share_dir}/wae/test/app_dek/*
index 905538e..d77016f 100644 (file)
@@ -103,17 +103,17 @@ int _get_random(raw_buffer_s *rb)
        return WAE_ERROR_NONE;
 }
 
-static const char *_get_dek_kek_pub_key_path()
+const char *_get_dek_kek_pub_key_path()
 {
        return tzplatform_mkpath4(TZ_SYS_SHARE, "wae", "app_dek", "WAE_APPDEK_KEK_PublicKey.pem");
 }
 
-static const char *_get_dek_kek_pri_key_path()
+const char *_get_dek_kek_pri_key_path()
 {
        return tzplatform_mkpath4(TZ_SYS_SHARE, "wae", "app_dek", "WAE_APPDEK_KEK_PrivateKey.pem");
 }
 
-static const char *_get_dek_store_path()
+const char *_get_dek_store_path()
 {
        return tzplatform_mkpath3(TZ_SYS_SHARE, "wae", "app_dek");
 }
@@ -188,6 +188,52 @@ error:
        return ret;
 }
 
+static void _remove_file(const char *path)
+{
+       unlink(path);
+}
+
+void _remove_directory(const char *path)
+{
+       char file_path_buff[MAX_PATH_LEN] = {0, };
+       DIR *dir = opendir(path);
+       if (dir == NULL) {
+               if (errno == ENOENT)
+                       WAE_SLOGI("directory is not exist already(%s)", path);
+               else
+                       WAE_SLOGE("Failed to open dir(%s)", path);
+
+               return;
+       }
+
+       struct dirent entry;
+       struct dirent *result = NULL;
+       while (true) {
+               if (readdir_r(dir, &entry, &result) != 0) {
+                       break;
+               } else if (result == NULL) {
+                       break;
+               } else if (strcmp(entry.d_name, ".") == 0 || strcmp(entry.d_name, "..") == 0) {
+                       continue;
+               }
+
+               if (snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s", path, entry.d_name)
+                               < 0)
+                       continue;
+
+               if (entry.d_type == DT_DIR) {
+                       _remove_directory(file_path_buff);
+               } else {
+                       WAE_SLOGD("remove file(%s)", file_path_buff);
+                       _remove_file(file_path_buff);
+               }
+       }
+
+       WAE_SLOGD("remove directory(%s)", path);
+       closedir(dir);
+       rmdir(path);
+}
+
 int _get_preloaded_app_dek_file_path(const char *pkg_id, size_t size, char *path)
 {
        int ret = snprintf(path, size, "%s/%s_%s.adek",
@@ -528,43 +574,53 @@ int _get_app_dek_kek(raw_buffer_s **pdek_kek)
 #endif
 }
 
-int load_preloaded_app_deks(bool reload)
+int load_preloaded_app_deks()
 {
-       int ret = WAE_ERROR_NONE;
+       WAE_SLOGI("load_preloaded_app_deks start");
 
-       char pkg_id[MAX_PKGID_LEN] = {0, };
-       char file_path_buff[MAX_PATH_LEN];
+       int global_ret = WAE_ERROR_NONE;
 
-       if (!reload) {
-               // check if all deks were already loaded into key-manager.
-               ret = is_app_deks_loaded_in_key_manager();
+       char pkg_id[MAX_PKGID_LEN] = {0, };
+       char file_path_buff[MAX_PATH_LEN] = {0, };
 
-               if (ret == true)
-                       return WAE_ERROR_NONE;
-       }
+       const char *dek_store_path = _get_dek_store_path();
+       const char *dek_kek_pub_key_path = _get_dek_kek_pub_key_path();
+       const char *dek_kek_pri_key_path = _get_dek_kek_pri_key_path();
 
        raw_buffer_s *prikey = NULL;
-       ret = _get_app_dek_kek(&prikey);
+       DIR *dir = NULL;
 
-       if (ret != WAE_ERROR_NONE) {
-               WAE_SLOGE("Fail to get APP_DEK_KEK Private Key");
-               return ret;
+       // check if all deks were already loaded into key-manager.
+       // TODO: instead of checking key-manager, check based on file existance
+       dir = opendir(dek_store_path);
+       if (dir == NULL) {
+               if (errno == ENOENT) {
+                       WAE_SLOGI(
+                               "dek store doesn't exist. "
+                               "It might be loading preloaded app deks already done");
+
+                       return WAE_ERROR_NONE;
+               } else {
+                       WAE_SLOGE("Fail to open dir. dir=%s", dek_store_path);
+                       global_ret = WAE_ERROR_FILE;
+                       goto out;
+               }
        }
 
-       DIR *dir = opendir(_get_dek_store_path());
+       global_ret = _get_app_dek_kek(&prikey);
 
-       if (dir == NULL) {
-               WAE_SLOGE("Fail to open dir. dir=%s", _get_dek_store_path());
-               buffer_destroy(prikey);
-               return WAE_ERROR_FILE;
+       if (global_ret != WAE_ERROR_NONE) {
+               WAE_SLOGE("Fail to get APP_DEK_KEK Private Key");
+               goto out;
        }
 
        struct dirent entry;
        struct dirent *result = NULL;
 
        while (true) {
+               int ret = WAE_ERROR_NONE;
                if (readdir_r(dir, &entry, &result) != 0) {
-                       ret = WAE_ERROR_FILE;
+                       global_ret = WAE_ERROR_FILE;
                        break;
                }
 
@@ -573,43 +629,77 @@ int load_preloaded_app_deks(bool reload)
                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)
+               if (strcmp(entry.d_name, ".") == 0 || strcmp(entry.d_name, "..") == 0)
                        continue;
 
-               ret = snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s",
-                                          _get_dek_store_path(), entry.d_name);
-
-               if (ret < 0) {
+               if (snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s",
+                                          dek_store_path, entry.d_name) < 0) {
                        WAE_SLOGE("Failed to make file path by snprintf.");
-                       ret = WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */
+                       global_ret = WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */
                        break;
                }
 
+               // skip for KEKs. They'll be deleted after all akek loaded to key-manager.
+               if (strcmp(file_path_buff, dek_kek_pub_key_path) == 0 ||
+                       strcmp(file_path_buff, dek_kek_pri_key_path) == 0) {
+                       WAE_SLOGD("Skip KEK file...(%s)", file_path_buff);
+                       continue;
+               }
+
+               // regular file && start with KEY_MANAGER_INITIAL_VALUE_FILE_PFX
+               // clear all invalid cases silently
+               if (entry.d_type != DT_REG || strstr(entry.d_name, APP_DEK_FILE_PFX) == NULL) {
+                       if (entry.d_type == DT_DIR) {
+                               WAE_SLOGW(
+                                       "Invalid file in dek store(%s). Directory shouldn't be here.",
+                                       dek_store_path);
+                               global_ret = WAE_ERROR_FILE;
+                       } else {
+                               WAE_SLOGW(
+                                       "Invalid file in dek store(%s). "
+                                       "Not regular file or prefix(%s) is invalid.",
+                                       dek_store_path, APP_DEK_FILE_PFX);
+                               global_ret = WAE_ERROR_FILE;
+                       }
+
+                       continue;
+               }
+
                ret = _extract_pkg_id_from_file_name(entry.d_name, pkg_id);
 
                if (ret != WAE_ERROR_NONE) {
                        WAE_SLOGW("Failed to extract pkgid from file. It will be ignored. file=%s",
                                          file_path_buff);
+                       global_ret = ret;
                        continue;
                }
 
                ret = _load_preloaded_app_dek(prikey, file_path_buff, pkg_id);
                if (ret != WAE_ERROR_NONE && ret != WAE_ERROR_KEY_EXISTS) {
                        WAE_SLOGW("Failed to load app dek(%s) ret(%d)", file_path_buff, ret);
+                       global_ret = ret;
                } else {
                        WAE_SLOGI("Successfully load app dek(%s)", file_path_buff);
-                       ret = WAE_ERROR_NONE;
                }
        }
 
-       buffer_destroy(prikey);
-       closedir(dir);
+out:
+       if (prikey != NULL)
+               buffer_destroy(prikey);
 
-       if (ret != WAE_ERROR_NONE)
-               return ret;
-       else
-               return set_app_deks_loaded_to_key_manager();
+       if (dir != NULL)
+               closedir(dir);
+
+       // remove dek store after loade done even though it's partially failed
+       // because malware can still put the file in dek store if it still system service's
+       // ownership and they can break this logic by inserting any file to dek store path.
+       // If KEK private key is inserted to key-manager with initial-value feature, malware
+       // cannot insert/encrypt/decrypt app dek so it's fine on preloaded app security but
+       // if we handle errors related loading file, malware can at least occur webappenc
+       // initializer service failure.
+       _remove_directory(dek_store_path);
+
+       return global_ret;
 }
 
 int remove_app_ce(uid_t uid, const char *pkg_id, wae_app_type_e app_type)
index 791e149..f5ce3e4 100644 (file)
@@ -41,6 +41,10 @@ int _get_random(raw_buffer_s *rb);
 int _get_preloaded_app_dek_file_path(const char *pkg_id, size_t size, char *path);
 int _read_encrypted_app_dek_from_file(const char *pkg_id, raw_buffer_s **pencrypted);
 int _write_encrypted_app_dek_to_file(const char *pkg_id, const raw_buffer_s *encrypted);
+void _remove_directory(const char *path);
+const char *_get_dek_kek_pub_key_path();
+const char *_get_dek_kek_pri_key_path();
+const char *_get_dek_store_path();
 
 /* functions for interface */
 int get_app_ce(uid_t uid, const char *pkg_id, wae_app_type_e app_type,
@@ -51,7 +55,7 @@ int remove_app_ce(uid_t uid, const char *pkg_id, wae_app_type_e app_type);
 
 int get_preloaded_app_ce(const char *pkg_id, const crypto_element_s **pce);
 int create_preloaded_app_ce(const char *pkg_id, const crypto_element_s **pce);
-int load_preloaded_app_deks(bool reload);
+int load_preloaded_app_deks();
 
 #ifdef __cplusplus
 }
index aeee748..ac42db2 100644 (file)
@@ -32,7 +32,6 @@
 
 #define MAX_ALIAS_LEN               256
 #define APP_DEK_ALIAS_PFX           "APP_DEK_"
-#define APP_DEK_LOADING_DONE_ALIAS  "APP_DEKS_LOADING_FINISHED"
 #define APP_DEK_KEK_ALIAS           "WAE_APP_DEK_KEK"
 
 static int _to_wae_error(int key_manager_error)
@@ -203,66 +202,6 @@ static void _get_alias(const char *name, UNUSED wae_app_type_e type, UNUSED bool
                         name);
 }
 
-static void _get_dek_loading_done_alias(char *alias, size_t buff_len)
-{
-       snprintf(alias, buff_len, "%s%s%s",
-                        ckmc_owner_id_system,
-                        ckmc_owner_id_separator,
-                        APP_DEK_LOADING_DONE_ALIAS);
-}
-
-bool is_app_deks_loaded_in_key_manager()
-{
-       char alias[MAX_ALIAS_LEN] = {0, };
-
-       _get_dek_loading_done_alias(alias, sizeof(alias));
-
-       ckmc_raw_buffer_s *buf = NULL;
-       int ret = _to_wae_error(ckmc_get_data(alias, NULL, &buf));
-
-       ckmc_buffer_free(buf);
-
-       switch (ret) {
-       case WAE_ERROR_NONE:
-               return true;
-       case WAE_ERROR_NO_KEY:
-               WAE_SLOGI("app dek loading isn't done yet");
-               return false;
-       default:
-               WAE_SLOGE("Failed to get dek loading flag data from key-manager. ret(%d)", ret);
-               return false;
-       }
-}
-
-int set_app_deks_loaded_to_key_manager()
-{
-       unsigned char dummy_data[1] = {0};
-       ckmc_raw_buffer_s buf;
-       buf.data = dummy_data;
-       buf.size = sizeof(dummy_data);
-
-       ckmc_policy_s policy;
-       policy.password = NULL;
-       policy.extractable = true;
-
-       char alias[MAX_ALIAS_LEN] = {0, };
-       _get_dek_loading_done_alias(alias, sizeof(alias));
-
-       int ret = _to_wae_error(ckmc_save_data(alias, buf, policy));
-       if (ret == WAE_ERROR_KEY_EXISTS)
-               ret = WAE_ERROR_NONE;
-
-       return ret;
-}
-
-int clear_app_deks_loaded_from_key_manager()
-{
-       char alias[MAX_ALIAS_LEN] = {0, };
-       _get_dek_loading_done_alias(alias, sizeof(alias));
-
-       return _to_wae_error(ckmc_remove_alias(alias));
-}
-
 int save_to_key_manager(const char *name, const char *pkg_id, wae_app_type_e type,
                                                const crypto_element_s *ce)
 {
index 956b04d..f01c8e8 100644 (file)
 #include "web_app_enc.h"
 #include "wae_log.h"
 
-int main(int argc, char *argv[])
+int main()
 {
-       bool reload = false;
-
-       if (argc == 2 && strcmp(argv[1], "--reload") == 0)
-               reload = true;
-
-       int ret = load_preloaded_app_deks(reload);
+       int ret = load_preloaded_app_deks();
 
        if (ret == WAE_ERROR_NONE) {
                WAE_SLOGI("WAE INITIALIZER was finished successfully.");
index 7c9e2c9..07d2082 100644 (file)
@@ -97,3 +97,5 @@ INSTALL(TARGETS ${TARGET_WAE_TEST}
                WORLD_READ
                WORLD_EXECUTE
 )
+
+ADD_SUBDIRECTORY(resources)
index 1fa9aff..7a13df7 100644 (file)
 
 #include <string>
 #include <cstring>
+#include <functional>
+#include <memory>
+#include <fstream>
 #include <unistd.h>
+#include <sys/stat.h>
+#include <dirent.h>
 
 #include <boost/test/unit_test.hpp>
 
@@ -32,6 +37,7 @@
 #include "crypto_service.h"
 
 #include "test-common.h"
+#include "test-helper.h"
 
 namespace {
 
@@ -76,7 +82,7 @@ crypto_element_s *_create_ce(void)
        return ce;
 }
 
-}
+} // namespace anonymous
 
 BOOST_AUTO_TEST_SUITE(SYSTEM)
 
@@ -261,6 +267,15 @@ BOOST_AUTO_TEST_CASE(read_write_encrypted_app_dek)
        BOOST_REQUIRE(dek != nullptr);
        BOOST_REQUIRE(_get_random(dek) == WAE_ERROR_NONE);
 
+       // precondition
+       //   dek store is removed after preloaded app deks loaded so dek store
+       //   does not exists as default. To test write/read app dek test(they're working on
+       //   dek store), dek store directory should be made
+       Wae::Test::restore_dek_store();
+       // make unique_ptr to remove directory automatically
+       std::unique_ptr<void, std::function<void(void *)>> scoped_store(
+               reinterpret_cast<void *>(1), [](void *) { Wae::Test::remove_dek_store(); });
+
        int ret = _write_encrypted_app_dek_to_file(pkg_id, dek);
        BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, "Failed to write_encrypted_app_dek_to_file. ec: " << ret);
 
@@ -276,7 +291,7 @@ BOOST_AUTO_TEST_CASE(read_write_encrypted_app_dek)
                        "readed(" << Wae::Test::bytes_to_hex(readed) << ")");
 }
 
-BOOST_AUTO_TEST_CASE(get_create_preloaded_app_dek_1)
+BOOST_AUTO_TEST_CASE(cache_create_preloaded_app_dek)
 {
        const char *pkg_id = "TEST_PKG_ID_FOR_CREATE";
 
@@ -287,7 +302,22 @@ BOOST_AUTO_TEST_CASE(get_create_preloaded_app_dek_1)
                        "preloaded app ce to create is already exist. ec: " << ret);
 
        const crypto_element_s *ce = nullptr;
-       ret = create_preloaded_app_ce(pkg_id, &ce);
+
+       {
+               // precondition:
+               // for create_preloaded_app_ce, public key(kek) is needed
+               Wae::Test::restore_dummy_preloaded_app_dek_keks();
+               // postcondition:
+               // get_preloaded_app_ce retrieves app ce from cache which is created on
+               // create_preloaded_app_ce so private key in dek store shouldn't be needed
+               // make unique_ptr to remove directory automatically
+               std::unique_ptr<void, std::function<void(void *)>> scoped_store(
+                       reinterpret_cast<void *>(1), [](void *) { Wae::Test::remove_dek_store(); });
+
+               // created preloaded app ce is just written in file, not into key-manager repo so
+               // no need to call remove_app_ce.
+               ret = create_preloaded_app_ce(pkg_id, &ce);
+       }
 
        BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE,
                        "Failed to create_preloaded_app_ce. ec: " << ret);
@@ -299,22 +329,21 @@ BOOST_AUTO_TEST_CASE(get_create_preloaded_app_dek_1)
        BOOST_REQUIRE_MESSAGE(readed == ce, "cached ce address and actual is different!");
 }
 
-BOOST_AUTO_TEST_CASE(get_create_preloaded_app_dek_2)
+BOOST_AUTO_TEST_CASE(load_preloaded_app_dek)
 {
+       // steps
+       //  1) restore KEKs : restore_dummy_preloaded_app_dek_keks
+       //  2) create app deks based on KEK (public key) : create_preloaded_app_ce
+       //     -> originally this step runs in image server so result(adek) is written to file
+       //  3) load preloaded app deks (.adek) in file : load_preloaded_app_deks
+       //     -> After load, pri/pub key pair and adek in file is no longer needed so they're
+       //        automatically cleared by load_preloaded_app_deks()
+       //  4) clear app deks from key-manager for remove it (associated to TEST_PKG_ID_*)
+       Wae::Test::restore_dummy_preloaded_app_dek_keks();
+
        const char *pkg_id1 = "TEST_PKGID_1";
        const char *pkg_id2 = "TEST_PKGID_2";
 
-       char path1[MAX_PATH_LEN] = {0, };
-       char path2[MAX_PATH_LEN] = {0, };
-       _get_preloaded_app_dek_file_path(pkg_id1, sizeof(path1), path1);
-       _get_preloaded_app_dek_file_path(pkg_id2, sizeof(path2), path2);
-
-       // remove old test data
-       remove_app_ce(0, pkg_id1, WAE_PRELOADED_APP);
-       remove_app_ce(0, pkg_id2, WAE_PRELOADED_APP);
-       unlink(path1);
-       unlink(path2);
-
        // create 2 ces for preloaded app
        const crypto_element_s *ce1 = nullptr;
        int ret = create_preloaded_app_ce(pkg_id1, &ce1);
@@ -326,7 +355,7 @@ BOOST_AUTO_TEST_CASE(get_create_preloaded_app_dek_2)
        BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE,
                        "Failed to create_preloaded_app_ce. ec: " << ret);
 
-       ret = load_preloaded_app_deks(true);
+       ret = load_preloaded_app_deks();
        BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE,
                        "Failed to load_preloaded_app_deks. ec: " << ret);
 
@@ -348,6 +377,48 @@ BOOST_AUTO_TEST_CASE(get_create_preloaded_app_dek_2)
        BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, "Failed remove app ce. ec: " << ret);
 }
 
+BOOST_AUTO_TEST_CASE(load_preloaded_app_dek_tolerances)
+{
+       std::function<bool()> does_dek_store_exist = []() {
+               if (DIR *dir = opendir(_get_dek_store_path())) {
+                       closedir(dir);
+                       return true;
+               } else if (errno != ENOENT) {
+                       return true;
+               } else {
+                       return false;
+               }
+       };
+
+       // without dek store directory
+       BOOST_REQUIRE(load_preloaded_app_deks() == WAE_ERROR_NONE);
+       BOOST_REQUIRE(does_dek_store_exist() == false);
+
+       // without kek(private key)
+       Wae::Test::restore_dek_store();
+       BOOST_REQUIRE(load_preloaded_app_deks() == WAE_ERROR_FILE);
+       BOOST_REQUIRE(does_dek_store_exist() == false);
+
+       // with invalid file in dek store
+       Wae::Test::restore_dummy_preloaded_app_dek_keks();
+       std::ofstream dst;
+       dst.exceptions(std::ofstream::failbit | std::ofstream::badbit);
+       dst.open(std::string(_get_dek_store_path()) + "/invalids", std::ofstream::binary);
+       dst << "touch invalid file to dek store";
+       // std::ofstream destructor will call close automatically so no need to handle
+       // close in the exception cases
+       dst.close();
+       BOOST_REQUIRE(load_preloaded_app_deks() == WAE_ERROR_FILE);
+       BOOST_REQUIRE(does_dek_store_exist() == false);
+
+       // with invalid directory in dek store
+       Wae::Test::restore_dummy_preloaded_app_dek_keks();
+       std::string invalid_dir = std::string(_get_dek_store_path()) + "/invalid_dir";
+       mkdir(invalid_dir.c_str(), S_IRUSR | S_IWUSR | S_IXUSR);
+       BOOST_REQUIRE(load_preloaded_app_deks() == WAE_ERROR_FILE);
+       BOOST_REQUIRE(does_dek_store_exist() == false);
+}
+
 BOOST_AUTO_TEST_SUITE_END() // INTERNALS
 
 BOOST_AUTO_TEST_SUITE_END() // SYSTEM
diff --git a/tests/resources/CMakeLists.txt b/tests/resources/CMakeLists.txt
new file mode 100644 (file)
index 0000000..fa0856f
--- /dev/null
@@ -0,0 +1,19 @@
+# Copyright (c) 2016 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.
+#
+INSTALL(
+    FILES pubkey.pem prikey.pem
+    DESTINATION ${RW_SHARE_DIR}/wae/test/app_dek
+    PERMISSIONS OWNER_READ
+)
diff --git a/tests/resources/prikey.pem b/tests/resources/prikey.pem
new file mode 100644 (file)
index 0000000..e27950c
--- /dev/null
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,F4C783D75B0679F29398E9A3CAB4733D
+
+kxgW1wGX3TZZ/wtv3g4AOLlZCHoQ6uXVQ0h2ofWjnJs8tas/alR6o8UBRIqCw44t
+znUvQ8HlThvzhGgxje/yDDSxCy9mqhgsi2XeTtAeUbMhFL6UArb3cs6M4a37lYoT
+llZdFyYkRWJ3vRS33TDrhXDV6GjZWQ05SJ0OYdPJsmA1ENwdH+5NE/xLnqLdTtWr
+O3Mn2vi6P9CVqZroCvYBzUaypGcmFhjTIbWmB6inXjoXyddzerh7PTDBDWWacBab
+C7gcZC5SrK5YOt6f54ANsVQO8jnkLDx95gUSHYthX1hrQ3Da5Gb6nfYP9RNrHCum
+O8RKxSOvv8zwbMlzqtld8xCOb7Nh04f8bofrzZVLZ0T92FcyFQmt1F4U6DNQqHsn
+AAqxRxUWsC5k2dX9uZ6RCpEzNYWyPvNe24I/Kt01Geoh1NtCns8CVZcrxyMMtZRK
+ZJnYhvNDXDQCDtMJjRBiEXXE++AdA2O6uFoGX3alKwtxAIjGI++pSRlz1GTps26x
+5mmLil5wb3KGBfMN4L0R0heDOeiPQrNv7CwX8OlHtA1OKFBtViWdd/uZ2hAko1Tz
+YkoYpHPQOV5LZ7dem/XNnwwel9g6AkHhLNJv5ih4Y0CQfPBSs+iiLbMHh/NaGDD9
++kbcf5Lk4FQGVbJDW9nDAXT6jjMyliTI+hIh5fM2k22qbq6OqBkW6EbOQDMP/R2P
+LhFqTgHceNt0mqpcDJdJQ0YKbxVpdkv5f1C4rW+pgUEeHDCQ7vPe4p44xQJ/Z/7Y
+AtPwPKzPPJze2cfoUkZd9jXN9g2v2555xnQZU78IEm1nPVBA+hLIaqN1hu1Lkzxy
+CwFNo7bMVh3FSBmZVtJlcLsyLxZ9UdoaSr+anfA0lWJPiBzE0whQljZp56l1rL1V
+1K8m/dc9rLJ3uDQmYoSRmBZG5zZlVWCip+R9VAHMxRi1x29dFk1jbtQscr63dMI8
+0eOUf28Mw719WWUZVzD08b431DPqWiqrpexUKEXPW8EsrINPfIg180QYt1VUoshs
+Tqi/LKM0OV6nlMGh9ieCK8WzVDW8F16krSLo6eJpIPYPZgkHE7fC7Jws1kpUrSnF
+GgT6rBA97tJ0EalinuFXbip1X087Quz5USURq18f7/B6nFu0Kd4GhlICsR24j3eB
+75SsTNmfUcko8s5QT4rwONEwtRffkGbbNEisCPcleJV68zHvN58mfD7Dl8W3zIO4
+Qk6B1Xy0C4EEniKFfjxIaMEaxrqntBIc+nZE6/+UoGp/Hj9r5ZdzQX2j4837IIdR
+CxT4tjXiWBA6u3WaLAZUSM0W0SEORUF9NwzlId1b8A3WxA8XewhAKPaJEr677vzZ
+083+neUOuXqqs597romLH1omuffxmHxBzmP+koUtemP78XxCBVWUAB1T+fBRJMz6
+9ZEgDWrMntJ1IaFoGdOWZELgwcXJ0KwWFuk+sieZ5WCCzNmFli9WPN/xSqwmdYw6
+RK9er5Vc8D9mAlmGlz2mpAmzNJHH30zYKT/d0XzBS8z6WBRthaTS3NLsiSeWdELH
+b5+WEMOiKvZ19AXU2unHw/XpeVnAISOHhumAqFCwXkjVoMt8LMDawt6ra8N8G+gD
+-----END RSA PRIVATE KEY-----
diff --git a/tests/resources/pubkey.pem b/tests/resources/pubkey.pem
new file mode 100644 (file)
index 0000000..f0dfcea
--- /dev/null
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0kWtjpRO7Zh2KX2naVE/
+BDJdrfwK9xexfNA0MkY2VJ4J2AKMYTj1D1jntceryupCEHOvP3rum+WsFvPXduz9
++VKnSsSqj4jcTUubtpDUGA5G79IqLEPFuSBaqI8Uwkzd08pE+s30oaJDnNazMhSq
+8JkqBPoCCwtUs73ruE9VbtsBO/kTlASIAfe8nXqcJLcDQgWYhizjJw0Pi6d74oCw
+S2OTvQDNvsXfFnA0ZJEEYw/rZLirj7OHoOjz+Sh5N+1uA3Up6SPPEbHuP6L12Yxq
+Hdy7gnJXodLhvE/cR4SN9VW7+qmCMBjmLkBejGrEX3STS9sLI7MZHu9Y26dwuYb4
++wIDAQAB
+-----END PUBLIC KEY-----
index d0ca263..b7fdf6a 100644 (file)
@@ -22,6 +22,9 @@
 
 #include <cstring>
 #include <vector>
+#include <fstream>
+#include <unistd.h>
+#include <sys/stat.h>
 
 #include "web_app_enc.h"
 #include "key_handler.h"
@@ -37,6 +40,25 @@ namespace {
 
 const uid_t UID_OWNER = 5001;
 
+void copy_file(const char *src_path, const char *dst_path)
+{
+       std::ifstream src;
+       std::ofstream dst;
+
+       src.exceptions(std::ifstream::failbit | std::ifstream::badbit);
+       dst.exceptions(std::ofstream::failbit | std::ofstream::badbit);
+
+       src.open(src_path, std::ifstream::binary);
+       dst.open(dst_path, std::ofstream::binary);
+
+       dst << src.rdbuf();
+
+       // std::ofstream destructor will call close automatically so no need to handle
+       // close in the exception cases
+       src.close();
+       dst.close();
+}
+
 } // namespace anonymous
 
 void add_get_remove_ce(wae_app_type_e app_type)
@@ -123,15 +145,29 @@ void encrypt_decrypt_web_app(wae_app_type_e app_type)
        else
                wae_remove_global_app_dek(pkg_id, app_type == WAE_PRELOADED_APP);
 
-       if (app_type == WAE_PRELOADED_APP)
-               clear_app_deks_loaded_from_key_manager();
-
        std::vector<unsigned char> plaintext = {
                'a', 'b', 'c', 'a', 'b', 'c', 'x', 'y',
                'o', 'q', '2', 'e', 'v', '0', '1', 'x'
        };
 
-       // test for downloaded web application
+       // precondition for preloaded app:
+       //   for preloaded app encryption, preloaded app dek kek(pub) is needed.
+       //   dek store is removed after preloaded app deks loaded so dek store
+       //   does not exists as default. To test encrypt/decrypt(write/read ce) app test,
+       //   dek store directory should be made.
+       std::unique_ptr<void, std::function<void(void *)>> scoped_store(
+               reinterpret_cast<void *>(1), [](void *ptr) {
+                       if (ptr == reinterpret_cast<void *>(1))
+                               return;
+                       else
+                               remove_dek_store(); // remove dek store automatically in case of error
+               });
+
+       if (app_type == WAE_PRELOADED_APP) {
+               restore_dummy_preloaded_app_dek_keks();
+               scoped_store.reset(reinterpret_cast<void *>(2));
+       }
+
        unsigned char *_encrypted = nullptr;
        size_t _enc_len = 0;
        int tmp = 0;
@@ -171,7 +207,7 @@ void encrypt_decrypt_web_app(wae_app_type_e app_type)
        }
 
        if (app_type == WAE_PRELOADED_APP)
-               load_preloaded_app_deks(true);
+               load_preloaded_app_deks();
 
        unsigned char *_decrypted = nullptr;
        size_t _dec_len = 0;
@@ -201,5 +237,31 @@ void encrypt_decrypt_web_app(wae_app_type_e app_type)
                        "Failed to wae_remove_app_dek. ec: " << tmp);
 }
 
+void restore_dek_store()
+{
+       mkdir(
+               _get_dek_store_path(),
+               S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP);
+}
+
+void remove_dek_store()
+{
+       _remove_directory(_get_dek_store_path());
+}
+
+void restore_dummy_preloaded_app_dek_keks()
+{
+       // Generate pri/pub key pair. Private key is protected
+       // with assigned password: APP_DEK_KEK_PRIKEY_PASSWORD) which is same to password
+       // of real private key because it's built in source of srcs/key_handler.c
+       // It should be removed after private key goes into key-manager initial-value.
+       restore_dek_store();
+
+       copy_file("/opt/share/wae/test/app_dek/prikey.pem", _get_dek_kek_pri_key_path());
+       copy_file("/opt/share/wae/test/app_dek/pubkey.pem", _get_dek_kek_pub_key_path());
+
+       BOOST_MESSAGE("copying dummy pri/pub key pair to dek store done");
+}
+
 } // namespace Test
 } // namespace Wae
index b4d1f42..cd2fae2 100644 (file)
@@ -29,5 +29,8 @@ void add_get_remove_ce(wae_app_type_e app_type);
 void create_app_ce(wae_app_type_e app_type);
 void encrypt_decrypt_web_app(wae_app_type_e app_type);
 
+void remove_dek_store();
+void restore_dek_store();
+void restore_dummy_preloaded_app_dek_keks();
 } // namespace Test
 } // namespace Wae