diff options
-rw-r--r-- | packaging/libwebappenc.spec | 1 | ||||
-rw-r--r-- | srcs/key_handler.c | 164 | ||||
-rw-r--r-- | srcs/key_handler.h | 6 | ||||
-rw-r--r-- | srcs/key_manager.c | 61 | ||||
-rw-r--r-- | srcs/wae_initializer.c | 9 | ||||
-rw-r--r-- | tests/CMakeLists.txt | 2 | ||||
-rw-r--r-- | tests/internals.cpp | 103 | ||||
-rw-r--r-- | tests/resources/CMakeLists.txt | 19 | ||||
-rw-r--r-- | tests/resources/prikey.pem | 30 | ||||
-rw-r--r-- | tests/resources/pubkey.pem | 9 | ||||
-rw-r--r-- | tests/test-helper.cpp | 72 | ||||
-rw-r--r-- | tests/test-helper.h | 3 |
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 |