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 Kyungwook Tak
20 * @brief Serialize/deserialize crypto element and save/get to key-manager
22 #include "key_manager.h"
28 #include <ckmc/ckmc-manager.h>
30 #include "web_app_enc.h"
33 #define MAX_ALIAS_LEN 256
34 #define APP_DEK_ALIAS_PFX "APP_DEK_"
35 #define APP_DEK_LOADING_DONE_ALIAS "APP_DEKS_LOADING_FINISHED"
36 #define APP_DEK_KEK_ALIAS "WAE_APP_DEK_KEK"
38 static int _to_wae_error(int key_manager_error)
40 switch (key_manager_error) {
42 return WAE_ERROR_NONE;
44 case CKMC_ERROR_INVALID_PARAMETER:
45 return WAE_ERROR_INVALID_PARAMETER;
47 case CKMC_ERROR_PERMISSION_DENIED:
48 return WAE_ERROR_PERMISSION_DENIED;
50 case CKMC_ERROR_DB_ALIAS_UNKNOWN:
51 return WAE_ERROR_NO_KEY;
53 case CKMC_ERROR_DB_ALIAS_EXISTS:
54 return WAE_ERROR_KEY_EXISTS;
56 case CKMC_ERROR_OUT_OF_MEMORY:
57 return WAE_ERROR_MEMORY;
60 return WAE_ERROR_KEY_MANAGER;
64 static int _serialize(const crypto_element_s *ce, ckmc_raw_buffer_s **pbuf)
66 if (!is_crypto_element_valid(ce) || pbuf == NULL)
67 return WAE_ERROR_INVALID_PARAMETER;
69 size_t total_len = sizeof(size_t) * 3 + ce->dek->size + ce->iv->size + sizeof(bool);
71 WAE_SLOGD("(serialization) total(%d) dek(%d) iv(%d) is_migrated(%d)",
72 total_len, ce->dek->size, ce->iv->size, ce->is_migrated_app);
74 unsigned char *_buf = (unsigned char *)malloc(total_len);
76 return WAE_ERROR_MEMORY;
78 ckmc_raw_buffer_s *buf = NULL;
79 int ret = _to_wae_error(ckmc_buffer_new(_buf, total_len, &buf));
83 if (ret != WAE_ERROR_NONE)
87 memcpy(buf->data, &total_len, sizeof(size_t));
88 pos += sizeof(size_t);
89 memcpy(buf->data + pos, &ce->dek->size, sizeof(size_t));
90 pos += sizeof(size_t);
91 memcpy(buf->data + pos, ce->dek->buf, ce->dek->size);
93 memcpy(buf->data + pos, &ce->iv->size, sizeof(size_t));
94 pos += sizeof(size_t);
95 memcpy(buf->data + pos, ce->iv->buf, ce->iv->size);
97 memcpy(buf->data + pos, &ce->is_migrated_app, sizeof(bool));
100 if (total_len != pos) {
101 WAE_SLOGE("(serialization) total len(%d) and actualy written byte(%d) "
102 "isn't matched!", total_len, pos);
103 ckmc_buffer_free(buf);
104 return WAE_ERROR_UNKNOWN;
109 WAE_SLOGD("(serialization) success!");
111 return WAE_ERROR_NONE;
114 static int _deserialize(const ckmc_raw_buffer_s *buf, crypto_element_s **pce)
116 if (buf == NULL || buf->data == NULL || buf->size == 0 || pce == NULL)
117 return WAE_ERROR_INVALID_PARAMETER;
121 bool is_migrated_app = false;
123 size_t total_len = 0;
124 crypto_element_s *ce = NULL;
126 memcpy(&total_len, buf->data, sizeof(size_t));
127 pos += sizeof(size_t);
129 if (buf->size != total_len) {
130 WAE_SLOGE("(deserialization) total len(%d) and actualy written byte(%d) "
131 "isn't matched!", total_len, buf->size);
132 return WAE_ERROR_UNKNOWN;
135 // deserialize dek size
136 memcpy(&dek_size, buf->data + pos, sizeof(size_t));
137 pos += sizeof(size_t);
139 raw_buffer_s *dek = buffer_create(dek_size);
141 return WAE_ERROR_MEMORY;
144 memcpy(dek->buf, buf->data + pos, dek->size);
147 // deserialize iv size
148 memcpy(&iv_size, buf->data + pos, sizeof(size_t));
149 pos += sizeof(size_t);
151 raw_buffer_s *iv = buffer_create(iv_size);
152 int ret = WAE_ERROR_NONE;
154 ret = WAE_ERROR_MEMORY;
159 memcpy(iv->buf, buf->data + pos, iv->size);
162 // deserialize is_migrated_app
163 memcpy(&is_migrated_app, buf->data + pos, sizeof(bool));
166 WAE_SLOGD("(deserialization) total(%d) dek(%d) iv(%d) is_migrated(%d)",
167 total_len, dek_size, iv_size, is_migrated_app);
169 if (pos != buf->size) {
170 WAE_SLOGE("(deserialization) raw buffer remained after deserializatation done!");
171 ret = WAE_ERROR_UNKNOWN;
175 ce = crypto_element_create(dek, iv);
177 ret = WAE_ERROR_MEMORY;
181 ce->is_migrated_app = is_migrated_app;
185 WAE_SLOGD("(deserialization) success!");
187 return WAE_ERROR_NONE;
196 static void _get_alias(const char *name, UNUSED wae_app_type_e type, UNUSED bool forSave,
197 char *alias, size_t buff_len)
199 snprintf(alias, buff_len, "%s%s%s%s",
200 ckmc_owner_id_system,
201 ckmc_owner_id_separator,
206 static void _get_dek_loading_done_alias(char *alias, size_t buff_len)
208 snprintf(alias, buff_len, "%s%s%s",
209 ckmc_owner_id_system,
210 ckmc_owner_id_separator,
211 APP_DEK_LOADING_DONE_ALIAS);
214 bool is_app_deks_loaded_in_key_manager()
216 char alias[MAX_ALIAS_LEN] = {0, };
218 _get_dek_loading_done_alias(alias, sizeof(alias));
220 ckmc_raw_buffer_s *buf = NULL;
221 int ret = _to_wae_error(ckmc_get_data(alias, NULL, &buf));
223 ckmc_buffer_free(buf);
228 case WAE_ERROR_NO_KEY:
229 WAE_SLOGI("app dek loading isn't done yet");
232 WAE_SLOGE("Failed to get dek loading flag data from key-manager. ret(%d)", ret);
237 int set_app_deks_loaded_to_key_manager()
239 unsigned char dummy_data[1] = {0};
240 ckmc_raw_buffer_s buf;
241 buf.data = dummy_data;
242 buf.size = sizeof(dummy_data);
244 ckmc_policy_s policy;
245 policy.password = NULL;
246 policy.extractable = true;
248 char alias[MAX_ALIAS_LEN] = {0, };
249 _get_dek_loading_done_alias(alias, sizeof(alias));
251 int ret = _to_wae_error(ckmc_save_data(alias, buf, policy));
252 if (ret == WAE_ERROR_KEY_EXISTS)
253 ret = WAE_ERROR_NONE;
258 int clear_app_deks_loaded_from_key_manager()
260 char alias[MAX_ALIAS_LEN] = {0, };
261 _get_dek_loading_done_alias(alias, sizeof(alias));
263 return _to_wae_error(ckmc_remove_alias(alias));
266 int save_to_key_manager(const char *name, const char *pkg_id, wae_app_type_e type,
267 const crypto_element_s *ce)
269 char alias[MAX_ALIAS_LEN] = {0, };
271 _get_alias(name, type, true, alias, sizeof(alias));
273 ckmc_raw_buffer_s *buf = NULL;
274 int ret = _serialize(ce, &buf);
275 if (ret != WAE_ERROR_NONE) {
276 WAE_SLOGE("Failed to serialize crypto element of name(%s)", name);
280 ckmc_policy_s policy;
281 policy.password = NULL;
282 policy.extractable = true;
284 ret = _to_wae_error(ckmc_save_data(alias, *buf, policy));
286 ckmc_buffer_free(buf);
288 if (ret != WAE_ERROR_NONE) {
289 WAE_SLOGE("Failed to add crypto element to ckm: name(%s) alias(%s) ret(%d)",
294 ret = _to_wae_error(ckmc_set_permission(alias, pkg_id, CKMC_PERMISSION_READ));
295 if (ret != WAE_ERROR_NONE) {
296 WAE_SLOGE("Failed to set perm of crypto element: pkg_id(%s) alias(%s) ret(%d)",
299 ckmc_remove_alias(alias); // rollback
303 WAE_SLOGI("Success to save crypto element to key-manager. name(%s)", name);
305 return WAE_ERROR_NONE;
308 int get_from_key_manager(const char *name, wae_app_type_e type, crypto_element_s **pce)
310 if (name == NULL || pce == NULL)
311 return WAE_ERROR_INVALID_PARAMETER;
313 char alias[MAX_ALIAS_LEN] = {0, };
315 _get_alias(name, type, false, alias, sizeof(alias));
317 ckmc_raw_buffer_s *buf = NULL;
318 int ret = _to_wae_error(ckmc_get_data(alias, NULL, &buf));
319 if (ret != WAE_ERROR_NONE)
322 ret = _deserialize(buf, pce);
324 ckmc_buffer_free(buf);
329 int remove_from_key_manager(const char *name, wae_app_type_e type)
331 char alias[MAX_ALIAS_LEN] = {0, };
333 _get_alias(name, type, true, alias, sizeof(alias));
335 return _to_wae_error(ckmc_remove_alias(alias));
338 static void _get_dek_kek_alias(char *alias, size_t buff_len)
340 snprintf(alias, buff_len, "%s%s%s",
341 ckmc_owner_id_system,
342 ckmc_owner_id_separator,
346 int get_dek_kek_from_key_manager(raw_buffer_s **pdek_kek)
348 if (pdek_kek == NULL)
349 return WAE_ERROR_INVALID_PARAMETER;
351 ckmc_raw_buffer_s *buf = NULL;
353 char alias[MAX_ALIAS_LEN] = {0, };
354 _get_dek_kek_alias(alias, sizeof(alias));
356 int ret = _to_wae_error(ckmc_get_data(alias, NULL, &buf));
357 if (ret != WAE_ERROR_NONE) {
358 WAE_SLOGE("Failed to get dek kek from key-manager. alias(%s) ret(%d)",
363 raw_buffer_s *dek_kek = buffer_create(buf->size);
364 if (dek_kek == NULL) {
365 ret = WAE_ERROR_MEMORY;
368 memcpy(dek_kek->buf, buf->data, dek_kek->size);
372 WAE_SLOGI("Success to get dek kek from key-manager.");
375 ckmc_buffer_free(buf);
377 if (ret != WAE_ERROR_NONE)
378 buffer_destroy(dek_kek);