diff options
Diffstat (limited to 'srcs/key_handler.c')
-rw-r--r-- | srcs/key_handler.c | 164 |
1 files changed, 127 insertions, 37 deletions
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) |