diff options
author | Kyungwook Tak <k.tak@samsung.com> | 2016-12-09 11:30:58 +0900 |
---|---|---|
committer | Kyungwook Tak <k.tak@samsung.com> | 2016-12-09 11:30:58 +0900 |
commit | 3898acb11d7a788f8233620fdf9e6f774a89e2c6 (patch) | |
tree | 9594136c8f46a4569a9409f99f6dd383b26cb4bd /srcs | |
parent | 1fcac8945420537f89d24a0e8e52ec99cc432674 (diff) | |
parent | 9fddab9e58ccd9acdecdbfcf12770c50feac4d2b (diff) | |
download | libwebappenc-accepted/tizen/3.0.m2/mobile/20170104.141733.tar.gz libwebappenc-accepted/tizen/3.0.m2/mobile/20170104.141733.tar.bz2 libwebappenc-accepted/tizen/3.0.m2/mobile/20170104.141733.zip |
Merge branch 'tizen' into tizen_3.0submit/tizen_3.0/20161212.020133submit/tizen_3.0.m2/20170104.093751accepted/tizen/3.0/wearable/20161213.023936accepted/tizen/3.0/tv/20161213.023915accepted/tizen/3.0/mobile/20161213.023904accepted/tizen/3.0/ivi/20161213.023947accepted/tizen/3.0/common/20161213.163513accepted/tizen/3.0.m2/wearable/20170104.142418accepted/tizen/3.0.m2/tv/20170104.142125accepted/tizen/3.0.m2/mobile/20170104.141733tizen_3.0_tvtizen_3.0.m2accepted/tizen_3.0.m2_wearableaccepted/tizen_3.0.m2_tvaccepted/tizen_3.0.m2_mobile
Change-Id: Ic6865eb0a587c50af8b81e929eb007f57c2bd1d0
Signed-off-by: Kyungwook Tak <k.tak@samsung.com>
Diffstat (limited to 'srcs')
-rw-r--r-- | srcs/key_handler.c | 224 | ||||
-rw-r--r-- | srcs/key_handler.h | 6 | ||||
-rw-r--r-- | srcs/key_manager.c | 61 | ||||
-rw-r--r-- | srcs/wae_initializer.c | 9 |
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."); |