summaryrefslogtreecommitdiff
path: root/srcs/key_handler.c
diff options
context:
space:
mode:
Diffstat (limited to 'srcs/key_handler.c')
-rw-r--r--srcs/key_handler.c164
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)