summaryrefslogtreecommitdiff
path: root/srcs/key_handler.c
diff options
context:
space:
mode:
authorKyungwook Tak <k.tak@samsung.com>2016-12-07 17:22:40 +0900
committerKyungwook Tak <k.tak@samsung.com>2016-12-08 15:09:41 +0900
commit66f4515064566676869fd3c3a8970fcf24b00b5f (patch)
treeab44c28901de718ad736b8e0517d591b50961eef /srcs/key_handler.c
parent9efcb91aed4e7365aa945fc9c6ffe2d111ca1496 (diff)
downloadlibwebappenc-66f4515064566676869fd3c3a8970fcf24b00b5f.tar.gz
libwebappenc-66f4515064566676869fd3c3a8970fcf24b00b5f.tar.bz2
libwebappenc-66f4515064566676869fd3c3a8970fcf24b00b5f.zip
Remove reload option to wae initializer service
Reload option is not needed anymore. To be secure, remove all KEKs from dek store (also adek) after loading preloaded adeks once. Loaded adeks are stored in key-manager so they're useless. Related test cases are added. (load preloaded app deks) (TODO) To use key-manager initial value feature is highly considered to store KEK private key more securely. Change-Id: I2f6c645398277968cd7d480236d1802a07fa33df Signed-off-by: Kyungwook Tak <k.tak@samsung.com>
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)