summaryrefslogtreecommitdiff
path: root/srcs
diff options
context:
space:
mode:
authorKyungwook Tak <k.tak@samsung.com>2016-12-09 11:30:58 +0900
committerKyungwook Tak <k.tak@samsung.com>2016-12-09 11:30:58 +0900
commit3898acb11d7a788f8233620fdf9e6f774a89e2c6 (patch)
tree9594136c8f46a4569a9409f99f6dd383b26cb4bd /srcs
parent1fcac8945420537f89d24a0e8e52ec99cc432674 (diff)
parent9fddab9e58ccd9acdecdbfcf12770c50feac4d2b (diff)
downloadlibwebappenc-accepted/tizen/3.0/wearable/20161213.023936.tar.gz
libwebappenc-accepted/tizen/3.0/wearable/20161213.023936.tar.bz2
libwebappenc-accepted/tizen/3.0/wearable/20161213.023936.zip
Change-Id: Ic6865eb0a587c50af8b81e929eb007f57c2bd1d0 Signed-off-by: Kyungwook Tak <k.tak@samsung.com>
Diffstat (limited to 'srcs')
-rw-r--r--srcs/key_handler.c224
-rw-r--r--srcs/key_handler.h6
-rw-r--r--srcs/key_manager.c61
-rw-r--r--srcs/wae_initializer.c9
4 files changed, 165 insertions, 135 deletions
diff --git a/srcs/key_handler.c b/srcs/key_handler.c
index 905538e..cdc96af 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,15 +188,87 @@ error:
return ret;
}
-int _get_preloaded_app_dek_file_path(const char *pkg_id, size_t size, char *path)
+typedef int(*entry_callback)(const char *path, const struct dirent *entry, void *user_data);
+static int traverse_directory(const char *path, entry_callback ecb, void *user_data)
+{
+ DIR *dir = opendir(path);
+ if (dir == NULL) {
+ if (errno == ENOENT) {
+ // it's not error for current cases of using traverse_directory.
+ // To open dek store directory for load/remove can be occured in some
+ // exception(or attacked) cases but we can just ignore it if it isn't the
+ // first time call load_preloaded_app_deks.
+ WAE_SLOGI("directory isn't exist(%s).", path);
+ return WAE_ERROR_NONE;
+ } else {
+ WAE_SLOGE("Failed to open dir(%s)", path);
+ return WAE_ERROR_FILE;
+ }
+ }
+
+ int ret = WAE_ERROR_NONE;
+ struct dirent entry;
+ struct dirent *result = NULL;
+ while (true) {
+ if (readdir_r(dir, &entry, &result) != 0) {
+ WAE_SLOGE("readdir_r error on dir(%s) errno(%d)", path, errno);
+ break;
+ } else if (result == NULL) {
+ break; // end of directory
+ } else if (strcmp(entry.d_name, ".") == 0 || strcmp(entry.d_name, "..") == 0) {
+ continue;
+ }
+
+ int _ret = ecb(path, result, user_data);
+ if (_ret != WAE_ERROR_NONE)
+ ret = _ret;
+ }
+
+ closedir(dir);
+ return ret;
+}
+
+static void _remove_file(const char *path)
{
- int ret = snprintf(path, size, "%s/%s_%s.adek",
- _get_dek_store_path(), APP_DEK_FILE_PFX, pkg_id);
+ unlink(path);
+}
+
+static int _entry_callback_remove_all(
+ const char *path, const struct dirent *entry, void *user_data)
+{
+ (void) user_data; // TODO: use UNUSED macro
- if (ret < 0)
+ char file_path_buff[MAX_PATH_LEN] = {0, };
+ if (snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s", path, entry->d_name) < 0)
return WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */
- return WAE_ERROR_NONE;
+ int ret = WAE_ERROR_NONE;
+ if (entry->d_type == DT_DIR) {
+ int _ret = traverse_directory(file_path_buff, _entry_callback_remove_all, NULL);
+ if (_ret != WAE_ERROR_NONE)
+ ret = _ret;
+ rmdir(file_path_buff);
+ } else {
+ _remove_file(file_path_buff);
+ }
+ return ret;
+}
+
+void _remove_directory(const char *path)
+{
+ traverse_directory(path, _entry_callback_remove_all, NULL);
+
+ WAE_SLOGD("remove directory(%s)", path);
+ rmdir(path);
+}
+
+int _get_preloaded_app_dek_file_path(const char *pkg_id, size_t size, char *path)
+{
+ if (snprintf(path, size, "%s/%s_%s.adek",
+ _get_dek_store_path(), APP_DEK_FILE_PFX, pkg_id) < 0)
+ return WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */
+ else
+ return WAE_ERROR_NONE;
}
static int _extract_pkg_id_from_file_name(const char *file_name, char *pkg_id)
@@ -528,88 +600,108 @@ int _get_app_dek_kek(raw_buffer_s **pdek_kek)
#endif
}
-int load_preloaded_app_deks(bool reload)
+static int _entry_callback_load_preloaded_adeks(
+ const char *path, const struct dirent *entry, void *prikey)
{
- int ret = WAE_ERROR_NONE;
+ const char *pub_key_path = _get_dek_kek_pub_key_path();
+ const char *pri_key_path = _get_dek_kek_pri_key_path();
- char pkg_id[MAX_PKGID_LEN] = {0, };
- char file_path_buff[MAX_PATH_LEN];
+ char file_path_buff[MAX_PATH_LEN] = {0, };
+ if (snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s", path, entry->d_name) < 0)
+ return WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */
- if (!reload) {
- // check if all deks were already loaded into key-manager.
- ret = is_app_deks_loaded_in_key_manager();
+ if (strcmp(file_path_buff, pub_key_path) == 0 ||
+ strcmp(file_path_buff, pri_key_path) == 0)
+ return WAE_ERROR_NONE; /* skip KEK files */
- if (ret == true)
- return WAE_ERROR_NONE;
- }
+ 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.", path);
+ else
+ WAE_SLOGW(
+ "Invalid file in dek store(%s). "
+ "Not regular file or prefix(%s) is invalid.", path, APP_DEK_FILE_PFX);
- raw_buffer_s *prikey = NULL;
- ret = _get_app_dek_kek(&prikey);
+ return WAE_ERROR_FILE;
+ }
+ char pkg_id[MAX_PKGID_LEN] = {0, };
+ int ret = _extract_pkg_id_from_file_name(entry->d_name, pkg_id);
if (ret != WAE_ERROR_NONE) {
- WAE_SLOGE("Fail to get APP_DEK_KEK Private Key");
+ WAE_SLOGW("Failed to extract pkgid from file(%s). It will be ignored.", file_path_buff);
return ret;
}
- DIR *dir = opendir(_get_dek_store_path());
-
- if (dir == NULL) {
- WAE_SLOGE("Fail to open dir. dir=%s", _get_dek_store_path());
- buffer_destroy(prikey);
- return WAE_ERROR_FILE;
+ ret = _load_preloaded_app_dek((raw_buffer_s *)prikey, file_path_buff, pkg_id);
+ if (ret == WAE_ERROR_NONE || ret == WAE_ERROR_KEY_EXISTS) {
+ WAE_SLOGI("Successfully load app dek(%s)", file_path_buff);
+ return WAE_ERROR_NONE;
+ } else {
+ WAE_SLOGW("Failed to load app dek(%s) ret(%d)", file_path_buff, ret);
+ return ret;
}
+}
- struct dirent entry;
- struct dirent *result = NULL;
-
- while (true) {
- if (readdir_r(dir, &entry, &result) != 0) {
- ret = WAE_ERROR_FILE;
- break;
- }
-
- // 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)
- continue;
+int load_preloaded_app_deks()
+{
+ WAE_SLOGI("load_preloaded_app_deks start");
- ret = snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s",
- _get_dek_store_path(), entry.d_name);
+ int ret = WAE_ERROR_NONE;
- if (ret < 0) {
- WAE_SLOGE("Failed to make file path by snprintf.");
- ret = WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */
- break;
- }
+ const char *dek_store_path = _get_dek_store_path();
- ret = _extract_pkg_id_from_file_name(entry.d_name, pkg_id);
+ raw_buffer_s *prikey = NULL;
+ DIR *dir = NULL;
- if (ret != WAE_ERROR_NONE) {
- WAE_SLOGW("Failed to extract pkgid from file. It will be ignored. file=%s",
- file_path_buff);
- continue;
- }
+ // 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");
- 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);
+ return WAE_ERROR_NONE;
} else {
- WAE_SLOGI("Successfully load app dek(%s)", file_path_buff);
- ret = WAE_ERROR_NONE;
+ WAE_SLOGE("Fail to open dir. dir=%s", dek_store_path);
+ ret = WAE_ERROR_FILE;
+ goto out;
}
}
- buffer_destroy(prikey);
+ ret = _get_app_dek_kek(&prikey);
+ if (ret != WAE_ERROR_NONE) {
+ WAE_SLOGE("Fail to get APP_DEK_KEK Private Key. ret(%d)", ret);
+ goto out;
+ }
+
+ // close dek store dir fd not to affect the traverse_directory call
closedir(dir);
+ dir = NULL;
+ ret = traverse_directory(dek_store_path, _entry_callback_load_preloaded_adeks, prikey);
if (ret != WAE_ERROR_NONE)
- return ret;
- else
- return set_app_deks_loaded_to_key_manager();
+ WAE_SLOGE("Fail when traverse dek store directory. ret(%d)", ret);
+
+out:
+ if (prikey != NULL)
+ buffer_destroy(prikey);
+
+ 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 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.");