2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
18 * @author Dongsun Lee (ds73.lee@samsung.com)
20 * @brief Key manupulatation.
22 #include "key_handler.h"
30 #include <tzplatform_config.h>
33 #include "crypto_service.h"
34 #include "key_manager.h"
35 #include "decrypt_migrated_wgt.h"
37 #define RANDOM_FILE "/dev/urandom"
38 #define APP_DEK_KEK_PRIKEY_PASSWORD "wae_appdek_kek_1q2w3e4r"
39 #define APP_DEK_FILE_PFX "WAE_APP_DEK"
43 #define MAX_PKGID_LEN 256
44 #define MAX_CACHE_SIZE 100
46 static unsigned char AES_CBC_IV[IV_LEN] = {
47 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
48 0x08, 0x39, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
51 static crypto_element_map_s *_map;
53 static void deinit_lib(void) __attribute__((destructor));
54 static void deinit_lib(void)
56 crypto_element_map_destroy(_map);
59 static const crypto_element_s *_get_app_ce_from_cache(const char *pkg_id)
61 return crypto_element_map_get(_map, pkg_id);
64 static int _add_app_ce_to_cache(const char *pkg_id, crypto_element_s *ce)
66 return crypto_element_map_add(&_map, pkg_id, ce);
69 void _remove_app_ce_from_cache(const char *pkg_id)
71 crypto_element_map_remove(&_map, pkg_id);
74 int _get_random(raw_buffer_s *rb)
76 if (!is_buffer_valid(rb))
77 return WAE_ERROR_INVALID_PARAMETER;
79 FILE *f = fopen(RANDOM_FILE, "r");
82 WAE_SLOGE("Failed to open random file source: %s", RANDOM_FILE);
83 return WAE_ERROR_FILE;
88 while (i < rb->size && (ch = fgetc(f) != EOF))
89 rb->buf[i++] = (unsigned char)ch;
93 return WAE_ERROR_NONE;
96 static const char *_get_dek_kek_pub_key_path()
98 return tzplatform_mkpath4(TZ_SYS_SHARE, "wae", "app_dek", "WAE_APPDEK_KEK_PublicKey.pem");
101 static const char *_get_dek_kek_pri_key_path()
103 return tzplatform_mkpath4(TZ_SYS_SHARE, "wae", "app_dek", "WAE_APPDEK_KEK_PrivateKey.pem");
106 static const char *_get_dek_store_path()
108 return tzplatform_mkpath3(TZ_SYS_SHARE, "wae", "app_dek");
111 static int _write_to_file(const char *path, const raw_buffer_s *data)
113 if (path == NULL || data == NULL || data->buf == NULL || data->size == 0)
114 return WAE_ERROR_INVALID_PARAMETER;
116 FILE *f = fopen(path, "w");
119 WAE_SLOGE("WAE: Fail to open a file. file=%s", path);
120 return WAE_ERROR_FILE;
123 int write_len = fwrite(data->buf, 1, data->size, f);
127 if (write_len != (int)data->size) {
128 WAE_SLOGE("WAE: Fail to write a file. file=%s", path);
129 return WAE_ERROR_FILE;
132 return WAE_ERROR_NONE;
135 static int _read_from_file(const char *path, raw_buffer_s **pdata)
137 int ret = WAE_ERROR_NONE;
138 raw_buffer_s *data = NULL;
142 FILE *f = fopen(path, "r");
145 WAE_SLOGE("Failed to open a file. file=%s", path);
146 return WAE_ERROR_FILE;
149 fseek(f, 0, SEEK_END); // move to the end of a file
150 int file_len = ftell(f);
153 WAE_SLOGE("Failed to get file size by ftell. ret: %d", file_len);
154 ret = WAE_ERROR_FILE;
158 fseek(f, 0, SEEK_SET); // move to the start of a file
160 data = buffer_create(file_len);
162 WAE_SLOGE("Failed to allocate memory for encrypted_dek");
163 ret = WAE_ERROR_MEMORY;
167 while ((ch = fgetc(f)) != EOF)
168 data->buf[i++] = (char)ch;
175 if (ret != WAE_ERROR_NONE)
176 buffer_destroy(data);
181 int _get_preloaded_app_dek_file_path(const char *pkg_id, size_t size, char *path)
183 int ret = snprintf(path, size, "%s/%s_%s.adek",
184 _get_dek_store_path(), APP_DEK_FILE_PFX, pkg_id);
187 return WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */
189 return WAE_ERROR_NONE;
192 static int _extract_pkg_id_from_file_name(const char *file_name, char *pkg_id)
194 char *start = strstr(file_name, APP_DEK_FILE_PFX);
197 WAE_SLOGE("WAE: Fail to extract pkgid from APP_DEK file. file_name=%s", file_name);
198 return WAE_ERROR_FILE;
201 start = start + strlen(APP_DEK_FILE_PFX) + 1;
202 char *end = strstr(file_name, ".adek");
205 WAE_SLOGE("WAE: Fail to extract pkgid from APP_DEK file. file_name=%s", file_name);
206 return WAE_ERROR_FILE;
209 strncpy(pkg_id, start, end - start);
210 pkg_id[end - start] = 0; //terminate string
212 return WAE_ERROR_NONE;
215 int _read_encrypted_app_dek_from_file(const char *pkg_id, raw_buffer_s **pencrypted)
217 char path[MAX_PATH_LEN] = {0,};
218 _get_preloaded_app_dek_file_path(pkg_id, sizeof(path), path);
219 return _read_from_file(path, pencrypted);
222 int _write_encrypted_app_dek_to_file(const char *pkg_id, const raw_buffer_s *encrypted)
224 char path[MAX_PATH_LEN] = {0,};
225 _get_preloaded_app_dek_file_path(pkg_id, sizeof(path), path);
226 return _write_to_file(path, encrypted);
229 int get_app_ce(const char *pkg_id, wae_app_type_e app_type, bool create_for_migrated_app,
230 const crypto_element_s **pce)
232 if (pkg_id == NULL || pce == NULL)
233 return WAE_ERROR_INVALID_PARAMETER;
235 const crypto_element_s *cached_ce = _get_app_ce_from_cache(pkg_id);
236 if (cached_ce != NULL) {
237 WAE_SLOGD("cache hit of app ce for pkg_id(%s)", pkg_id);
239 return WAE_ERROR_NONE;
242 WAE_SLOGD("cache miss of app ce for pkg_id(%s)", pkg_id);
244 crypto_element_s *ce = NULL;
245 int ret = get_from_key_manager(pkg_id, app_type, &ce);
247 if (create_for_migrated_app &&
248 (ret == WAE_ERROR_NO_KEY && app_type == WAE_DOWNLOADED_GLOBAL_APP)) {
249 WAE_SLOGI("No dek found for pkg_id(%s)! It should be migrated app.", pkg_id);
251 if ((ret = get_old_ss_crypto_element(pkg_id, &ce)) != WAE_ERROR_NONE)
254 // (k.tak) disable to save ce to key-maanger for migrated app because of permission issue.
255 //ret = save_to_key_manager(pkg_id, app_type, ce);
256 //if (ret != WAE_ERROR_NONE) {
257 // WAE_SLOGW("Failed to save migrated app ce to key-manager with ret(%d). "
258 // "Ignore this error because we can create ce later again.", ret);
259 // ret = WAE_ERROR_NONE;
261 } else if (ret != WAE_ERROR_NONE) {
262 WAE_SLOGE("Failed to get crypto element from key-manager. pkg_id=%s, ret=%d",
267 ret = _add_app_ce_to_cache(pkg_id, ce);
268 if (ret != WAE_ERROR_NONE) {
269 WAE_SLOGE("Failed to add ce to cache for pkg_id(%s) ret(%d)", pkg_id, ret);
275 WAE_SLOGD("Successfully get ce! pkgid(%s)", pkg_id);
277 return WAE_ERROR_NONE;
280 crypto_element_destroy(ce);
285 int create_app_ce(const char *pkg_id, wae_app_type_e app_type, const crypto_element_s **pce)
287 raw_buffer_s *dek = buffer_create(DEK_LEN);
288 raw_buffer_s *iv = buffer_create(IV_LEN);
289 crypto_element_s *ce = crypto_element_create(dek, iv);
291 int ret = WAE_ERROR_NONE;
294 ret = WAE_ERROR_MEMORY;
298 memcpy(ce->iv->buf, AES_CBC_IV, ce->iv->size);
300 ret = _get_random(dek);
301 if (ret != WAE_ERROR_NONE) {
302 WAE_SLOGE("Failed to get random for dek. pkg_id(%s) ret(%d)", pkg_id, ret);
306 ret = save_to_key_manager(pkg_id, app_type, ce);
307 if (ret != WAE_ERROR_NONE) {
308 WAE_SLOGE("Failed to save ce to key-manager. pkg_id(%s) app_type(%d) ret(%d)",
309 pkg_id, app_type, ret);
313 ret = _add_app_ce_to_cache(pkg_id, ce);
314 if (ret != WAE_ERROR_NONE) {
315 WAE_SLOGE("Failed to add ce to cache for pkg_id(%s) ret(%d)", pkg_id, ret);
321 WAE_SLOGI("Success to create dek/iv and store it in key-manager. pkg_id(%s)", pkg_id);
323 return WAE_ERROR_NONE;
330 crypto_element_destroy(ce);
336 int get_preloaded_app_ce(const char *pkg_id, const crypto_element_s **pce)
338 const crypto_element_s *cached_ce = _get_app_ce_from_cache(pkg_id);
340 if (cached_ce == NULL) {
341 WAE_SLOGE("WAE: Fail to get APP_DEK from cache for preloaded app");
342 return WAE_ERROR_NO_KEY;
347 return WAE_ERROR_NONE;
350 int create_preloaded_app_ce(const char *pkg_id, const crypto_element_s **pce)
352 raw_buffer_s *encrypted_app_dek = NULL;
353 raw_buffer_s *pubkey = NULL;
354 raw_buffer_s *dek = buffer_create(DEK_LEN);
355 raw_buffer_s *iv = buffer_create(sizeof(AES_CBC_IV));
356 crypto_element_s *ce = crypto_element_create(dek, iv);
358 int ret = WAE_ERROR_NONE;
360 if (dek == NULL || iv == NULL || ce == NULL) {
361 ret = WAE_ERROR_MEMORY;
365 ret = _get_random(dek);
367 if (ret != WAE_ERROR_NONE)
370 // copy default iv for preloaded app
371 memcpy(iv->buf, AES_CBC_IV, sizeof(AES_CBC_IV));
373 ret = _read_from_file(_get_dek_kek_pub_key_path(), &pubkey);
375 if (ret != WAE_ERROR_NONE) {
376 WAE_SLOGE("WAE: Fail to read APP_DEK_KEK Public Key");
380 ret = encrypt_app_dek(pubkey, dek, &encrypted_app_dek);
382 if (ret != WAE_ERROR_NONE) {
383 WAE_SLOGE("WAE: Fail to encrypt APP_DEK with APP_DEK_KEK");
387 // write APP_DEK in a file
388 ret = _write_encrypted_app_dek_to_file(pkg_id, encrypted_app_dek);
390 if (ret != WAE_ERROR_NONE) {
391 WAE_SLOGE("Failed to write encrypted dek to file. pkg_id(%s)", pkg_id);
395 // store APP_DEK in cache
396 _add_app_ce_to_cache(pkg_id, ce);
397 if (ret != WAE_ERROR_NONE) {
398 WAE_SLOGE("Failed to add ce to cache for pkg_id(%s) ret(%d)", pkg_id, ret);
404 WAE_SLOGI("Success to create preleaded dek and write it in initial value file. "
405 "pkg_id(%s)", pkg_id);
408 buffer_destroy(encrypted_app_dek);
409 buffer_destroy(pubkey);
411 if (ret != WAE_ERROR_NONE) {
413 crypto_element_destroy(ce);
423 int _get_app_dek_kek(raw_buffer_s **pdek_kek)
426 return get_dek_kek_from_key_manager(pdek_kek);
428 return _read_from_file(_get_dek_kek_pri_key_path(), pdek_kek);
432 int load_preloaded_app_deks(bool reload)
434 int ret = WAE_ERROR_NONE;
436 char pkg_id[MAX_PKGID_LEN] = {0, };
438 char file_path_buff[MAX_PATH_LEN];
439 raw_buffer_s *encrypted_dek = NULL;
440 raw_buffer_s *dek = NULL;
441 raw_buffer_s *iv = NULL;
442 raw_buffer_s *prikey = NULL;
443 crypto_element_s *ce = NULL;
445 int error_during_loading = 0;
448 // check if all deks were already loaded into key-manager.
449 ret = is_app_deks_loaded_in_key_manager();
451 if (ret == WAE_ERROR_NONE)
455 ret = _get_app_dek_kek(&prikey);
457 if (ret != WAE_ERROR_NONE) {
458 WAE_SLOGE("Fail to get APP_DEK_KEK Private Key");
462 DIR *dir = opendir(_get_dek_store_path());
465 WAE_SLOGE("Fail to open dir. dir=%s", _get_dek_store_path());
466 return WAE_ERROR_FILE;
470 struct dirent *result = NULL;
473 int error = readdir_r(dir, &entry, &result);
476 ret = WAE_ERROR_FILE;
480 // readdir_r returns NULL in *result if the end
481 // of the directory stream is reached
485 // regular file && start with KEY_MANAGER_INITIAL_VALUE_FILE_PFX
486 if (entry.d_type != DT_REG || strstr(entry.d_name, APP_DEK_FILE_PFX) == NULL)
489 ret = snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s",
490 _get_dek_store_path(), entry.d_name);
493 WAE_SLOGE("Failed to make file path by snprintf.");
494 ret = WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */
498 ret = _extract_pkg_id_from_file_name(entry.d_name, pkg_id);
500 if (ret != WAE_ERROR_NONE) {
501 WAE_SLOGW("Failed to extract pkgid from file. It will be ignored. file=%s",
506 ret = _read_from_file(file_path_buff, &encrypted_dek);
508 if (ret != WAE_ERROR_NONE || encrypted_dek == NULL) {
509 ++error_during_loading;
510 WAE_SLOGW("Failed to read file. It will be ignored. file=%s", file_path_buff);
514 ret = decrypt_app_dek(prikey, APP_DEK_KEK_PRIKEY_PASSWORD, encrypted_dek, &dek);
516 buffer_destroy(encrypted_dek);
517 encrypted_dek = NULL;
519 if (ret != WAE_ERROR_NONE || dek == NULL) {
520 ++error_during_loading;
521 WAE_SLOGW("Failed to decrypt dek. It will be ignored. file=%s",
525 iv = buffer_create(IV_LEN);
527 ++error_during_loading;
533 memcpy(iv->buf, AES_CBC_IV, iv->size);
535 ce = crypto_element_create(dek, iv);
537 ++error_during_loading;
545 ret = save_to_key_manager(pkg_id, WAE_PRELOADED_APP, ce);
547 if (ret == WAE_ERROR_KEY_EXISTS) {
548 WAE_SLOGI("Key Manager already has dek. It will be ignored. file=%s",
550 } else if (ret != WAE_ERROR_NONE) {
551 ++error_during_loading;
552 WAE_SLOGW("Fail to add APP DEK to key-manager. file=%s", file_path_buff);
555 crypto_element_destroy(ce);
559 ret = set_app_deks_loaded_to_key_manager();
562 if (ret != WAE_ERROR_NONE) {
564 crypto_element_destroy(ce);
571 buffer_destroy(prikey);
577 int remove_app_ce(const char *pkg_id, wae_app_type_e app_type)
579 int ret = remove_from_key_manager(pkg_id, app_type);
581 if (ret != WAE_ERROR_NONE)
582 WAE_SLOGE("Failed to remove app ce for pkg_id(%s) ret(%d)", pkg_id, ret);
584 WAE_SLOGI("Success to remove app ce for pkg_id(%s)", pkg_id);
586 _remove_app_ce_from_cache(pkg_id);