summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyungwook Tak <k.tak@samsung.com>2016-12-07 17:22:40 +0900
committerKyungwook Tak <k.tak@samsung.com>2016-12-08 15:09:41 +0900
commit66f4515064566676869fd3c3a8970fcf24b00b5f (patch)
treeab44c28901de718ad736b8e0517d591b50961eef
parent9efcb91aed4e7365aa945fc9c6ffe2d111ca1496 (diff)
downloadlibwebappenc-66f4515064566676869fd3c3a8970fcf24b00b5f.tar.gz
libwebappenc-66f4515064566676869fd3c3a8970fcf24b00b5f.tar.bz2
libwebappenc-66f4515064566676869fd3c3a8970fcf24b00b5f.zip
Remove reload option to wae initializer service
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>
-rw-r--r--packaging/libwebappenc.spec1
-rw-r--r--srcs/key_handler.c164
-rw-r--r--srcs/key_handler.h6
-rw-r--r--srcs/key_manager.c61
-rw-r--r--srcs/wae_initializer.c9
-rw-r--r--tests/CMakeLists.txt2
-rw-r--r--tests/internals.cpp103
-rw-r--r--tests/resources/CMakeLists.txt19
-rw-r--r--tests/resources/prikey.pem30
-rw-r--r--tests/resources/pubkey.pem9
-rw-r--r--tests/test-helper.cpp72
-rw-r--r--tests/test-helper.h3
12 files changed, 352 insertions, 127 deletions
diff --git a/packaging/libwebappenc.spec b/packaging/libwebappenc.spec
index 760f3e2..4184b84 100644
--- a/packaging/libwebappenc.spec
+++ b/packaging/libwebappenc.spec
@@ -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/*
diff --git a/srcs/key_handler.c b/srcs/key_handler.c
index 905538e..d77016f 100644
--- a/srcs/key_handler.c
+++ b/srcs/key_handler.c
@@ -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)
diff --git a/srcs/key_handler.h b/srcs/key_handler.h
index 791e149..f5ce3e4 100644
--- a/srcs/key_handler.h
+++ b/srcs/key_handler.h
@@ -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
}
diff --git a/srcs/key_manager.c b/srcs/key_manager.c
index aeee748..ac42db2 100644
--- a/srcs/key_manager.c
+++ b/srcs/key_manager.c
@@ -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)
{
diff --git a/srcs/wae_initializer.c b/srcs/wae_initializer.c
index 956b04d..f01c8e8 100644
--- a/srcs/wae_initializer.c
+++ b/srcs/wae_initializer.c
@@ -23,14 +23,9 @@
#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.");
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 7c9e2c9..07d2082 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -97,3 +97,5 @@ INSTALL(TARGETS ${TARGET_WAE_TEST}
WORLD_READ
WORLD_EXECUTE
)
+
+ADD_SUBDIRECTORY(resources)
diff --git a/tests/internals.cpp b/tests/internals.cpp
index 1fa9aff..7a13df7 100644
--- a/tests/internals.cpp
+++ b/tests/internals.cpp
@@ -24,7 +24,12 @@
#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
index 0000000..fa0856f
--- /dev/null
+++ b/tests/resources/CMakeLists.txt
@@ -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
index 0000000..e27950c
--- /dev/null
+++ b/tests/resources/prikey.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/tests/resources/pubkey.pem b/tests/resources/pubkey.pem
new file mode 100644
index 0000000..f0dfcea
--- /dev/null
+++ b/tests/resources/pubkey.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/tests/test-helper.cpp b/tests/test-helper.cpp
index d0ca263..b7fdf6a 100644
--- a/tests/test-helper.cpp
+++ b/tests/test-helper.cpp
@@ -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
diff --git a/tests/test-helper.h b/tests/test-helper.h
index b4d1f42..cd2fae2 100644
--- a/tests/test-helper.h
+++ b/tests/test-helper.h
@@ -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