Refine directory traversing: registering callback
[platform/core/security/libwebappenc.git] / srcs / key_handler.c
1 /*
2  *  Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License
15  *
16  *
17  * @file        key_handler.c
18  * @author      Dongsun Lee (ds73.lee@samsung.com)
19  * @version     1.0
20  * @brief       Key manupulatation.
21  */
22 #include "key_handler.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <dirent.h>
28 #include <unistd.h>
29
30 #include <tzplatform_config.h>
31
32 #include "web_app_enc.h"
33 #include "wae_log.h"
34 #include "crypto_service.h"
35 #include "key_manager.h"
36 #include "decrypt_migrated_wgt.h"
37
38 #define RANDOM_FILE                 "/dev/urandom"
39 #define APP_DEK_KEK_PRIKEY_PASSWORD "wae_appdek_kek_1q2w3e4r"
40 #define APP_DEK_FILE_PFX            "WAE_APP_DEK"
41
42 #define DEK_LEN        32
43 #define IV_LEN         16
44 #define MAX_PKGID_LEN  256
45 #define MAX_CACHE_SIZE 100
46
47 static unsigned char AES_CBC_IV[IV_LEN] = {
48         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
49         0x08, 0x39, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
50 };
51
52 static crypto_element_map_s *_map;
53
54 static void deinit_lib(void) __attribute__((destructor));
55 static void deinit_lib(void)
56 {
57         crypto_element_map_destroy(_map);
58 }
59
60 char *_create_map_key(uid_t uid, const char *pkg_id)
61 {
62         char *key = NULL;
63
64         int ret = asprintf(&key, "%u-%s", uid, pkg_id);
65
66         return (ret == -1) ? NULL : key;
67 }
68
69 static const crypto_element_s *_get_app_ce_from_cache(const char *key)
70 {
71         return crypto_element_map_get(_map, key);
72 }
73
74 static int _add_app_ce_to_cache(const char *key, crypto_element_s *ce)
75 {
76         return crypto_element_map_add(&_map, key, ce);
77 }
78
79 void _remove_app_ce_from_cache(const char *key)
80 {
81         crypto_element_map_remove(&_map, key);
82 }
83
84 int _get_random(raw_buffer_s *rb)
85 {
86         if (!is_buffer_valid(rb))
87                 return WAE_ERROR_INVALID_PARAMETER;
88
89         FILE *f = fopen(RANDOM_FILE, "r");
90
91         if (f == NULL) {
92                 WAE_SLOGE("Failed to open random file source: %s", RANDOM_FILE);
93                 return WAE_ERROR_FILE;
94         }
95
96         size_t i = 0;
97         int ch = 0;
98         while (i < rb->size && (ch = fgetc(f) != EOF))
99                 rb->buf[i++] = (unsigned char)ch;
100
101         fclose(f);
102
103         return WAE_ERROR_NONE;
104 }
105
106 const char *_get_dek_kek_pub_key_path()
107 {
108         return tzplatform_mkpath4(TZ_SYS_SHARE, "wae", "app_dek", "WAE_APPDEK_KEK_PublicKey.pem");
109 }
110
111 const char *_get_dek_kek_pri_key_path()
112 {
113         return tzplatform_mkpath4(TZ_SYS_SHARE, "wae", "app_dek", "WAE_APPDEK_KEK_PrivateKey.pem");
114 }
115
116 const char *_get_dek_store_path()
117 {
118         return tzplatform_mkpath3(TZ_SYS_SHARE, "wae", "app_dek");
119 }
120
121 static int _write_to_file(const char *path, const raw_buffer_s *data)
122 {
123         if (path == NULL || !is_buffer_valid(data))
124                 return WAE_ERROR_INVALID_PARAMETER;
125
126         FILE *f = fopen(path, "w");
127
128         if (f == NULL) {
129                 WAE_SLOGE("Failed to open a file(%s)", path);
130                 return WAE_ERROR_FILE;
131         }
132
133         int write_len = fwrite(data->buf, 1, data->size, f);
134
135         fclose(f);
136
137         if (write_len != (int)data->size) {
138                 WAE_SLOGE("Failed to write a file(%s)", path);
139                 return WAE_ERROR_FILE;
140         }
141
142         return WAE_ERROR_NONE;
143 }
144
145 static int _read_from_file(const char *path, raw_buffer_s **pdata)
146 {
147         int ret = WAE_ERROR_NONE;
148         raw_buffer_s *data = NULL;
149         int ch = 0;
150         int i = 0;
151
152         FILE *f = fopen(path, "r");
153
154         if (f == NULL) {
155                 WAE_SLOGE("Failed to open a file. file=%s", path);
156                 return WAE_ERROR_FILE;
157         }
158
159         fseek(f, 0, SEEK_END); // move to the end of a file
160         int file_len = ftell(f);
161
162         if (file_len <= 0) {
163                 WAE_SLOGE("Failed to get file size by ftell. ret: %d", file_len);
164                 ret = WAE_ERROR_FILE;
165                 goto error;
166         }
167
168         fseek(f, 0, SEEK_SET); // move to the start of a file
169
170         data = buffer_create(file_len);
171         if (data == NULL) {
172                 WAE_SLOGE("Failed to allocate memory for encrypted_dek");
173                 ret = WAE_ERROR_MEMORY;
174                 goto error;
175         }
176
177         while ((ch = fgetc(f)) != EOF)
178                 data->buf[i++] = (char)ch;
179
180         *pdata = data;
181
182 error:
183         fclose(f);
184
185         if (ret != WAE_ERROR_NONE)
186                 buffer_destroy(data);
187
188         return ret;
189 }
190
191 typedef int(*entry_callback)(const char *path, const struct dirent *entry, void *user_data);
192 static int traverse_directory(const char *path, entry_callback ecb, void *user_data)
193 {
194         DIR *dir = opendir(path);
195         if (dir == NULL) {
196                 if (errno == ENOENT) {
197                         // it's not error for current cases of using traverse_directory.
198                         // To open dek store directory for load/remove can be occured in some
199                         // exception(or attacked) cases but we can just ignore it if it isn't the
200                         // first time call load_preloaded_app_deks.
201                         WAE_SLOGI("directory isn't exist(%s).", path);
202                         return WAE_ERROR_NONE;
203                 } else {
204                         WAE_SLOGE("Failed to open dir(%s)", path);
205                         return WAE_ERROR_FILE;
206                 }
207         }
208
209         int ret = WAE_ERROR_NONE;
210         struct dirent entry;
211         struct dirent *result = NULL;
212         while (true) {
213                 if (readdir_r(dir, &entry, &result) != 0) {
214                         WAE_SLOGE("readdir_r error on dir(%s) errno(%d)", path, errno);
215                         break;
216                 } else if (result == NULL) {
217                         break; // end of directory
218                 } else if (strcmp(entry.d_name, ".") == 0 || strcmp(entry.d_name, "..") == 0) {
219                         continue;
220                 }
221
222                 int _ret = ecb(path, result, user_data);
223                 if (_ret != WAE_ERROR_NONE)
224                         ret = _ret;
225         }
226
227         closedir(dir);
228         return ret;
229 }
230
231 static void _remove_file(const char *path)
232 {
233         unlink(path);
234 }
235
236 static int _entry_callback_remove_all(
237         const char *path, const struct dirent *entry, void *user_data)
238 {
239         (void) user_data; // TODO: use UNUSED macro
240
241         char file_path_buff[MAX_PATH_LEN] = {0, };
242         if (snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s", path, entry->d_name) < 0)
243                 return WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */
244
245         int ret = WAE_ERROR_NONE;
246         if (entry->d_type == DT_DIR) {
247                 int _ret = traverse_directory(file_path_buff, _entry_callback_remove_all, NULL);
248                 if (_ret != WAE_ERROR_NONE)
249                         ret = _ret;
250                 rmdir(file_path_buff);
251         } else {
252                 _remove_file(file_path_buff);
253         }
254         return ret;
255 }
256
257 void _remove_directory(const char *path)
258 {
259         traverse_directory(path, _entry_callback_remove_all, NULL);
260
261         WAE_SLOGD("remove directory(%s)", path);
262         rmdir(path);
263 }
264
265 int _get_preloaded_app_dek_file_path(const char *pkg_id, size_t size, char *path)
266 {
267         if (snprintf(path, size, "%s/%s_%s.adek",
268                                 _get_dek_store_path(), APP_DEK_FILE_PFX, pkg_id) < 0)
269                 return WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */
270         else
271                 return WAE_ERROR_NONE;
272 }
273
274 static int _extract_pkg_id_from_file_name(const char *file_name, char *pkg_id)
275 {
276         char *start = strstr(file_name, APP_DEK_FILE_PFX);
277
278         if (start == NULL) {
279                 WAE_SLOGE("WAE: Fail to extract pkgid from APP_DEK file. file_name=%s", file_name);
280                 return WAE_ERROR_FILE;
281         }
282
283         start = start + strlen(APP_DEK_FILE_PFX) + 1;
284         char *end = strstr(file_name, ".adek");
285
286         if (end == NULL) {
287                 WAE_SLOGE("WAE: Fail to extract pkgid from APP_DEK file. file_name=%s", file_name);
288                 return WAE_ERROR_FILE;
289         }
290
291         strncpy(pkg_id, start, end - start);
292         pkg_id[end - start] = 0; //terminate string
293
294         return WAE_ERROR_NONE;
295 }
296
297 int _read_encrypted_app_dek_from_file(const char *pkg_id, raw_buffer_s **pencrypted)
298 {
299         char path[MAX_PATH_LEN] = {0,};
300         _get_preloaded_app_dek_file_path(pkg_id, sizeof(path), path);
301         return _read_from_file(path, pencrypted);
302 }
303
304 int _write_encrypted_app_dek_to_file(const char *pkg_id, const raw_buffer_s *encrypted)
305 {
306         char path[MAX_PATH_LEN] = {0,};
307         _get_preloaded_app_dek_file_path(pkg_id, sizeof(path), path);
308         return _write_to_file(path, encrypted);
309 }
310
311 int _load_preloaded_app_dek(
312         const raw_buffer_s *prikey, const char *filepath, const char *pkg_id)
313 {
314         raw_buffer_s *encrypted_dek = NULL;
315         raw_buffer_s *dek = NULL;
316         raw_buffer_s *iv = NULL;
317         crypto_element_s *ce = NULL;
318
319         int ret = _read_from_file(filepath, &encrypted_dek);
320         if (ret != WAE_ERROR_NONE) {
321                 WAE_SLOGW("Failed to read file. It will be ignored. file=%s", filepath);
322                 return ret;
323         }
324
325         ret = decrypt_app_dek(prikey, APP_DEK_KEK_PRIKEY_PASSWORD, encrypted_dek, &dek);
326         if (ret != WAE_ERROR_NONE) {
327                 WAE_SLOGW("Failed to decrypt dek. It will be ignored. file=%s", filepath);
328                 goto finish;
329         }
330
331         iv = buffer_create(IV_LEN);
332         if (iv == NULL) {
333                 ret = WAE_ERROR_MEMORY;
334                 goto finish;
335         }
336
337         memcpy(iv->buf, AES_CBC_IV, iv->size);
338
339         ce = crypto_element_create(dek, iv);
340         if (ce == NULL) {
341                 ret = WAE_ERROR_MEMORY;
342                 goto finish;
343         }
344
345         ret = save_to_key_manager(pkg_id, pkg_id, WAE_PRELOADED_APP, ce);
346         if (ret == WAE_ERROR_KEY_EXISTS) {
347                 WAE_SLOGI("Key Manager already has dek. It will be ignored. file=%s", filepath);
348         } else if (ret != WAE_ERROR_NONE) {
349                 WAE_SLOGW("Fail to add APP DEK to key-manager. file=%s", filepath);
350         }
351
352 finish:
353         buffer_destroy(encrypted_dek);
354
355         if (ce == NULL) {
356                 buffer_destroy(dek);
357                 buffer_destroy(iv);
358         } else {
359                 crypto_element_destroy(ce);
360         }
361
362         return ret;
363 }
364
365 int get_app_ce(uid_t uid, const char *pkg_id, wae_app_type_e app_type,
366                            bool create_for_migrated_app, const crypto_element_s **pce)
367 {
368         if (pkg_id == NULL || pce == NULL)
369                 return WAE_ERROR_INVALID_PARAMETER;
370
371         if (uid == 0 && app_type == WAE_DOWNLOADED_NORMAL_APP)
372                 return WAE_ERROR_INVALID_PARAMETER;
373
374         const char *key = NULL;
375         char *_key_per_user = NULL;
376
377         if (app_type == WAE_DOWNLOADED_NORMAL_APP) {
378                 _key_per_user = _create_map_key(uid, pkg_id);
379                 if (_key_per_user == NULL)
380                         return WAE_ERROR_MEMORY;
381
382                 key = _key_per_user;
383         } else {
384                 key = pkg_id;
385         }
386
387         int ret = WAE_ERROR_NONE;
388         const crypto_element_s *cached_ce = _get_app_ce_from_cache(key);
389         if (cached_ce != NULL) {
390                 WAE_SLOGD("cache hit of app ce for key(%s)", key);
391                 *pce = cached_ce;
392                 goto finish;
393         }
394
395         WAE_SLOGD("cache miss of app ce for key(%s)", key);
396
397         crypto_element_s *ce = NULL;
398         ret = get_from_key_manager(key, app_type, &ce);
399
400         if (create_for_migrated_app &&
401                         (ret == WAE_ERROR_NO_KEY && app_type == WAE_DOWNLOADED_GLOBAL_APP)) {
402                 WAE_SLOGI("No dek found for key(%s)! It should be migrated app.", key);
403
404                 if ((ret = get_old_ss_crypto_element(key, &ce)) != WAE_ERROR_NONE)
405                         goto finish;
406
407                 // (k.tak) disable to save ce to key-maanger for migrated app because of permission issue.
408                 //ret = save_to_key_manager(key, pkg_id, app_type, ce);
409                 //if (ret != WAE_ERROR_NONE) {
410                 //      WAE_SLOGW("Failed to save migrated app ce to key-manager with ret(%d). "
411                 //                        "Ignore this error because we can create ce later again.", ret);
412                 //      ret = WAE_ERROR_NONE;
413                 //}
414         } else if (ret != WAE_ERROR_NONE) {
415                 WAE_SLOGE("Failed to get crypto element from key-manager. key(%s) ret(%d)",
416                                   key, ret);
417                 goto finish;
418         }
419
420         ret = _add_app_ce_to_cache(key, ce);
421         if (ret != WAE_ERROR_NONE) {
422                 WAE_SLOGE("Failed to add ce to cache for key(%s) ret(%d)", key, ret);
423                 goto finish;
424         }
425
426         *pce = ce;
427
428         WAE_SLOGD("Successfully get ce! key(%s)", key);
429
430 finish:
431         free(_key_per_user);
432
433         if (ret != WAE_ERROR_NONE)
434                 crypto_element_destroy(ce);
435
436         return ret;
437 }
438
439 int create_app_ce(uid_t uid, const char *pkg_id, wae_app_type_e app_type,
440                                   const crypto_element_s **pce)
441 {
442         raw_buffer_s *dek = buffer_create(DEK_LEN);
443         raw_buffer_s *iv = buffer_create(IV_LEN);
444         crypto_element_s *ce = crypto_element_create(dek, iv);
445
446         int ret = WAE_ERROR_NONE;
447         const char *key = NULL;
448         char *_key_per_user = NULL;
449
450         if (ce == NULL) {
451                 ret = WAE_ERROR_MEMORY;
452                 goto error;
453         }
454
455         if (app_type == WAE_DOWNLOADED_NORMAL_APP) {
456                 _key_per_user = _create_map_key(uid, pkg_id);
457                 if (_key_per_user == NULL) {
458                         ret = WAE_ERROR_MEMORY;
459                         goto error;
460                 }
461
462                 key = _key_per_user;
463         } else {
464                 key = pkg_id;
465         }
466
467         memcpy(ce->iv->buf, AES_CBC_IV, ce->iv->size);
468
469         ret = _get_random(dek);
470         if (ret != WAE_ERROR_NONE) {
471                 WAE_SLOGE("Failed to get random for dek. key(%s) ret(%d)", key, ret);
472                 goto error;
473         }
474
475         ret = save_to_key_manager(key, pkg_id, app_type, ce);
476         if (ret != WAE_ERROR_NONE) {
477                 WAE_SLOGE("Failed to save ce to key-manager. key(%s) app_type(%d) ret(%d)",
478                                   key, app_type, ret);
479                 goto error;
480         }
481
482         ret = _add_app_ce_to_cache(key, ce);
483         if (ret != WAE_ERROR_NONE) {
484                 WAE_SLOGE("Failed to add ce to cache for key(%s) ret(%d)", key, ret);
485                 goto error;
486         }
487
488         *pce = ce;
489
490         WAE_SLOGI("Success to create dek/iv and store it in key-manager. key(%s)", key);
491
492 error:
493         if (ret != WAE_ERROR_NONE) {
494                 if (ce == NULL) {
495                         buffer_destroy(dek);
496                         buffer_destroy(iv);
497                 } else {
498                         crypto_element_destroy(ce);
499                 }
500         }
501
502         free(_key_per_user);
503
504         return ret;
505 }
506
507 int get_preloaded_app_ce(const char *pkg_id, const crypto_element_s **pce)
508 {
509         const crypto_element_s *cached_ce = _get_app_ce_from_cache(pkg_id);
510
511         if (cached_ce == NULL) {
512                 WAE_SLOGE("WAE: Fail to get APP_DEK from cache for preloaded app");
513                 return WAE_ERROR_NO_KEY;
514         }
515
516         *pce = cached_ce;
517
518         return WAE_ERROR_NONE;
519 }
520
521 int create_preloaded_app_ce(const char *pkg_id, const crypto_element_s **pce)
522 {
523         raw_buffer_s *encrypted_app_dek = NULL;
524         raw_buffer_s *pubkey = NULL;
525         raw_buffer_s *dek = buffer_create(DEK_LEN);
526         raw_buffer_s *iv = buffer_create(sizeof(AES_CBC_IV));
527         crypto_element_s *ce = crypto_element_create(dek, iv);
528
529         int ret = WAE_ERROR_NONE;
530
531         if (dek == NULL || iv == NULL || ce == NULL) {
532                 ret = WAE_ERROR_MEMORY;
533                 goto error;
534         }
535
536         ret = _get_random(dek);
537
538         if (ret != WAE_ERROR_NONE)
539                 goto error;
540
541         // copy default iv for preloaded app
542         memcpy(iv->buf, AES_CBC_IV, sizeof(AES_CBC_IV));
543
544         ret = _read_from_file(_get_dek_kek_pub_key_path(), &pubkey);
545
546         if (ret != WAE_ERROR_NONE) {
547                 WAE_SLOGE("WAE: Fail to read APP_DEK_KEK Public Key");
548                 goto error;
549         }
550
551         ret = encrypt_app_dek(pubkey, dek, &encrypted_app_dek);
552
553         if (ret != WAE_ERROR_NONE) {
554                 WAE_SLOGE("WAE: Fail to encrypt APP_DEK with APP_DEK_KEK");
555                 goto error;
556         }
557
558         // write APP_DEK in a file
559         ret = _write_encrypted_app_dek_to_file(pkg_id, encrypted_app_dek);
560
561         if (ret != WAE_ERROR_NONE) {
562                 WAE_SLOGE("Failed to write encrypted dek to file. pkg_id(%s)", pkg_id);
563                 goto error;
564         }
565
566         // store APP_DEK in cache
567         ret = _add_app_ce_to_cache(pkg_id, ce);
568         if (ret != WAE_ERROR_NONE) {
569                 WAE_SLOGE("Failed to add ce to cache for pkg_id(%s) ret(%d)", pkg_id, ret);
570                 goto error;
571         }
572
573         *pce = ce;
574
575         WAE_SLOGI("Success to create preleaded dek and write it in initial value file. "
576                           "pkg_id(%s)", pkg_id);
577
578 error:
579         buffer_destroy(encrypted_app_dek);
580         buffer_destroy(pubkey);
581
582         if (ret != WAE_ERROR_NONE) {
583                 if (ce) {
584                         crypto_element_destroy(ce);
585                 } else {
586                         buffer_destroy(dek);
587                         buffer_destroy(iv);
588                 }
589         }
590
591         return ret;
592 }
593
594 int _get_app_dek_kek(raw_buffer_s **pdek_kek)
595 {
596 #if 0
597         return get_dek_kek_from_key_manager(pdek_kek);
598 #else
599         return _read_from_file(_get_dek_kek_pri_key_path(), pdek_kek);
600 #endif
601 }
602
603 static int _entry_callback_load_preloaded_adeks(
604         const char *path, const struct dirent *entry, void *prikey)
605 {
606         const char *pub_key_path = _get_dek_kek_pub_key_path();
607         const char *pri_key_path = _get_dek_kek_pri_key_path();
608
609         char file_path_buff[MAX_PATH_LEN] = {0, };
610         if (snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s", path, entry->d_name) < 0)
611                 return WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */
612
613         if (strcmp(file_path_buff, pub_key_path) == 0 ||
614                 strcmp(file_path_buff, pri_key_path) == 0)
615                 return WAE_ERROR_NONE; /* skip KEK files */
616
617         if (entry->d_type != DT_REG || strstr(entry->d_name, APP_DEK_FILE_PFX) == NULL) {
618                 if (entry->d_type == DT_DIR)
619                         WAE_SLOGW(
620                                 "Invalid file in dek store(%s). Directory shouldn't be here.", path);
621                 else
622                         WAE_SLOGW(
623                                 "Invalid file in dek store(%s). "
624                                 "Not regular file or prefix(%s) is invalid.", path, APP_DEK_FILE_PFX);
625
626                 return WAE_ERROR_FILE;
627         }
628
629         char pkg_id[MAX_PKGID_LEN] = {0, };
630         int ret = _extract_pkg_id_from_file_name(entry->d_name, pkg_id);
631         if (ret != WAE_ERROR_NONE) {
632                 WAE_SLOGW("Failed to extract pkgid from file(%s). It will be ignored.", file_path_buff);
633                 return ret;
634         }
635
636         ret = _load_preloaded_app_dek((raw_buffer_s *)prikey, file_path_buff, pkg_id);
637         if (ret == WAE_ERROR_NONE || ret == WAE_ERROR_KEY_EXISTS) {
638                 WAE_SLOGI("Successfully load app dek(%s)", file_path_buff);
639                 return WAE_ERROR_NONE;
640         } else {
641                 WAE_SLOGW("Failed to load app dek(%s) ret(%d)", file_path_buff, ret);
642                 return ret;
643         }
644 }
645
646 int load_preloaded_app_deks()
647 {
648         WAE_SLOGI("load_preloaded_app_deks start");
649
650         int ret = WAE_ERROR_NONE;
651
652         const char *dek_store_path = _get_dek_store_path();
653
654         raw_buffer_s *prikey = NULL;
655         DIR *dir = NULL;
656
657         // check if all deks were already loaded into key-manager.
658         // TODO: instead of checking key-manager, check based on file existance
659         dir = opendir(dek_store_path);
660         if (dir == NULL) {
661                 if (errno == ENOENT) {
662                         WAE_SLOGI(
663                                 "dek store doesn't exist. "
664                                 "It might be loading preloaded app deks already done");
665
666                         return WAE_ERROR_NONE;
667                 } else {
668                         WAE_SLOGE("Fail to open dir. dir=%s", dek_store_path);
669                         ret = WAE_ERROR_FILE;
670                         goto out;
671                 }
672         }
673
674         ret = _get_app_dek_kek(&prikey);
675         if (ret != WAE_ERROR_NONE) {
676                 WAE_SLOGE("Fail to get APP_DEK_KEK Private Key. ret(%d)", ret);
677                 goto out;
678         }
679
680         // close dek store dir fd not to affect the traverse_directory call
681         closedir(dir);
682         dir = NULL;
683
684         ret = traverse_directory(dek_store_path, _entry_callback_load_preloaded_adeks, prikey);
685         if (ret != WAE_ERROR_NONE)
686                 WAE_SLOGE("Fail when traverse dek store directory. ret(%d)", ret);
687
688 out:
689         if (prikey != NULL)
690                 buffer_destroy(prikey);
691
692         if (dir != NULL)
693                 closedir(dir);
694
695         // remove dek store after loade done even though it's partially failed
696         // because malware can still put the file in dek store if it still system service's
697         // ownership and they can break this logic by inserting any file to dek store path.
698         // If KEK private key is inserted to key-manager with initial-value feature, malware
699         // cannot insert/encrypt/decrypt app dek so it's fine on preloaded app security but
700         // if we handle errors related loading file, malware can at least occur webappenc
701         // initializer service failure.
702         _remove_directory(dek_store_path);
703
704         return ret;
705 }
706
707 int remove_app_ce(uid_t uid, const char *pkg_id, wae_app_type_e app_type)
708 {
709         if (uid == 0 && app_type == WAE_DOWNLOADED_NORMAL_APP)
710                 return WAE_ERROR_INVALID_PARAMETER;
711
712         const char *key = NULL;
713         char *_key_per_user = NULL;
714
715         if (app_type == WAE_DOWNLOADED_NORMAL_APP) {
716                 _key_per_user = _create_map_key(uid, pkg_id);
717                 if (_key_per_user == NULL)
718                         return WAE_ERROR_MEMORY;
719
720                 key = _key_per_user;
721         } else {
722                 key = pkg_id;
723         }
724
725         int ret = remove_from_key_manager(key, app_type);
726
727         if (ret != WAE_ERROR_NONE)
728                 WAE_SLOGE("Failed to remove app ce for key(%s) ret(%d)", key, ret);
729         else
730                 WAE_SLOGI("Success to remove app ce for key(%s)", key);
731
732         _remove_app_ce_from_cache(key);
733
734         free(_key_per_user);
735
736         return ret;
737 }