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>
32 #define MAX_ALIAS_LEN 256
33 #define APP_DEK_ALIAS_PFX "APP_DEK_"
34 #define APP_DEK_LOADING_DONE_ALIAS "APP_DEKS_LOADING_FINISHED"
35 #define APP_DEK_KEK_ALIAS "WAE_APP_DEK_KEK"
37 static int _to_wae_error(int key_manager_error)
39 switch (key_manager_error) {
41 return WAE_ERROR_NONE;
43 case CKMC_ERROR_INVALID_PARAMETER:
44 return WAE_ERROR_INVALID_PARAMETER;
46 case CKMC_ERROR_PERMISSION_DENIED:
47 return WAE_ERROR_PERMISSION_DENIED;
49 case CKMC_ERROR_DB_ALIAS_UNKNOWN:
50 return WAE_ERROR_NO_KEY;
52 case CKMC_ERROR_DB_ALIAS_EXISTS:
53 return WAE_ERROR_KEY_EXISTS;
55 case CKMC_ERROR_OUT_OF_MEMORY:
56 return WAE_ERROR_MEMORY;
59 return WAE_ERROR_KEY_MANAGER;
63 static int _serialize(const crypto_element_s *ce, ckmc_raw_buffer_s **pbuf)
65 if (!is_crypto_element_valid(ce) || pbuf == NULL)
66 return WAE_ERROR_INVALID_PARAMETER;
68 size_t total_len = sizeof(size_t) * 3 + ce->dek->size + ce->iv->size + sizeof(bool);
70 WAE_SLOGD("(serialization) total(%d) dek(%d) iv(%d) is_migrated(%d)",
71 total_len, ce->dek->size, ce->iv->size, ce->is_migrated_app);
73 unsigned char *_buf = (unsigned char *)malloc(total_len);
75 return WAE_ERROR_MEMORY;
77 ckmc_raw_buffer_s *buf = NULL;
78 int ret = _to_wae_error(ckmc_buffer_new(_buf, total_len, &buf));
82 if (ret != WAE_ERROR_NONE)
86 memcpy(buf->data, &total_len, sizeof(size_t));
87 pos += sizeof(size_t);
88 memcpy(buf->data + pos, &ce->dek->size, sizeof(size_t));
89 pos += sizeof(size_t);
90 memcpy(buf->data + pos, ce->dek->buf, ce->dek->size);
92 memcpy(buf->data + pos, &ce->iv->size, sizeof(size_t));
93 pos += sizeof(size_t);
94 memcpy(buf->data + pos, ce->iv->buf, ce->iv->size);
96 memcpy(buf->data + pos, &ce->is_migrated_app, sizeof(bool));
99 if (total_len != pos) {
100 WAE_SLOGE("(serialization) total len(%d) and actualy written byte(%d) "
101 "isn't matched!", total_len, pos);
102 ckmc_buffer_free(buf);
103 return WAE_ERROR_UNKNOWN;
108 WAE_SLOGD("(serialization) success!");
110 return WAE_ERROR_NONE;
113 static int _deserialize(const ckmc_raw_buffer_s *buf, crypto_element_s **pce)
115 if (buf == NULL || buf->data == NULL || buf->size == 0 || pce == NULL)
116 return WAE_ERROR_INVALID_PARAMETER;
120 bool is_migrated_app = false;
122 size_t total_len = 0;
123 crypto_element_s *ce = NULL;
125 memcpy(&total_len, buf->data, sizeof(size_t));
126 pos += sizeof(size_t);
128 if (buf->size != total_len) {
129 WAE_SLOGE("(deserialization) total len(%d) and actualy written byte(%d) "
130 "isn't matched!", total_len, buf->size);
131 return WAE_ERROR_UNKNOWN;
134 // deserialize dek size
135 memcpy(&dek_size, buf->data + pos, sizeof(size_t));
136 pos += sizeof(size_t);
138 raw_buffer_s *dek = buffer_create(dek_size);
140 return WAE_ERROR_MEMORY;
143 memcpy(dek->buf, buf->data + pos, dek->size);
146 // deserialize iv size
147 memcpy(&iv_size, buf->data + pos, sizeof(size_t));
148 pos += sizeof(size_t);
150 raw_buffer_s *iv = buffer_create(iv_size);
151 int ret = WAE_ERROR_NONE;
153 ret = WAE_ERROR_MEMORY;
158 memcpy(iv->buf, buf->data + pos, iv->size);
161 // deserialize is_migrated_app
162 memcpy(&is_migrated_app, buf->data + pos, sizeof(bool));
165 WAE_SLOGD("(deserialization) total(%d) dek(%d) iv(%d) is_migrated(%d)",
166 total_len, dek_size, iv_size, is_migrated_app);
168 if (pos != buf->size) {
169 WAE_SLOGE("(deserialization) raw buffer remained after deserializatation done!");
170 ret = WAE_ERROR_UNKNOWN;
174 ce = crypto_element_create(dek, iv);
176 ret = WAE_ERROR_MEMORY;
180 ce->is_migrated_app = is_migrated_app;
184 WAE_SLOGD("(deserialization) success!");
186 return WAE_ERROR_NONE;
195 static void _get_alias(const char *pkg_id, wae_app_type_e type, bool forSave,
196 char *alias, size_t buff_len)
198 if (type == WAE_DOWNLOADED_NORMAL_APP) {
200 snprintf(alias, buff_len, "%s%s",
204 snprintf(alias, buff_len, "%c%s%s%s%s",
205 '/', INSTALLER_LABEL,
206 ckmc_owner_id_separator,
210 } else { // system alias
211 snprintf(alias, buff_len, "%s%s%s%s",
212 ckmc_owner_id_system,
213 ckmc_owner_id_separator,
219 static void _get_dek_loading_done_alias(char *alias, size_t buff_len)
221 snprintf(alias, buff_len, "%s%s%s",
222 ckmc_owner_id_system,
223 ckmc_owner_id_separator,
224 APP_DEK_LOADING_DONE_ALIAS);
227 bool is_app_deks_loaded_in_key_manager()
229 char alias[MAX_ALIAS_LEN] = {0, };
231 _get_dek_loading_done_alias(alias, sizeof(alias));
233 ckmc_raw_buffer_s *buf = NULL;
234 int ret = _to_wae_error(ckmc_get_data(alias, NULL, &buf));
236 ckmc_buffer_free(buf);
241 case WAE_ERROR_NO_KEY:
242 WAE_SLOGI("app dek loading isn't done yet");
245 WAE_SLOGE("Failed to get dek loading flag data from key-manager. ret(%d)", ret);
250 int set_app_deks_loaded_to_key_manager()
252 unsigned char dummy_data[1] = {0};
253 ckmc_raw_buffer_s buf;
254 buf.data = dummy_data;
255 buf.size = sizeof(dummy_data);
257 ckmc_policy_s policy;
258 policy.password = NULL;
259 policy.extractable = true;
261 char alias[MAX_ALIAS_LEN] = {0, };
262 _get_dek_loading_done_alias(alias, sizeof(alias));
264 int ret = _to_wae_error(ckmc_save_data(alias, buf, policy));
265 if (ret == WAE_ERROR_KEY_EXISTS)
266 ret = WAE_ERROR_NONE;
271 int clear_app_deks_loaded_from_key_manager()
273 char alias[MAX_ALIAS_LEN] = {0, };
274 _get_dek_loading_done_alias(alias, sizeof(alias));
276 return _to_wae_error(ckmc_remove_alias(alias));
279 int save_to_key_manager(const char *pkg_id, wae_app_type_e type, const crypto_element_s *ce)
281 char alias[MAX_ALIAS_LEN] = {0, };
283 _get_alias(pkg_id, type, true, alias, sizeof(alias));
285 ckmc_raw_buffer_s *buf = NULL;
286 int ret = _serialize(ce, &buf);
287 if (ret != WAE_ERROR_NONE) {
288 WAE_SLOGE("Failed to serialize crypto element of pkg_id: %s", pkg_id);
292 ckmc_policy_s policy;
293 policy.password = NULL;
294 policy.extractable = true;
296 ret = _to_wae_error(ckmc_save_data(alias, *buf, policy));
298 ckmc_buffer_free(buf);
300 if (ret != WAE_ERROR_NONE) {
301 WAE_SLOGE("Failed to add crypto element to ckm: pkg_id(%s) alias(%s) ret(%d)",
306 ret = _to_wae_error(ckmc_set_permission(alias, pkg_id, CKMC_PERMISSION_READ));
307 if (ret != WAE_ERROR_NONE) {
308 WAE_SLOGE("Failed to set perm of crypto element: pkg_id(%s) alias(%s) ret(%d)",
311 ckmc_remove_alias(alias); // rollback
315 WAE_SLOGI("Success to save crypto element to key-manager. pkg_id(%s)", pkg_id);
317 return WAE_ERROR_NONE;
320 int get_from_key_manager(const char *pkg_id, wae_app_type_e type, crypto_element_s **pce)
322 if (pkg_id == NULL || pce == NULL)
323 return WAE_ERROR_INVALID_PARAMETER;
325 char alias[MAX_ALIAS_LEN] = {0, };
327 _get_alias(pkg_id, type, false, alias, sizeof(alias));
329 ckmc_raw_buffer_s *buf = NULL;
330 int ret = _to_wae_error(ckmc_get_data(alias, NULL, &buf));
331 if (ret != WAE_ERROR_NONE)
334 ret = _deserialize(buf, pce);
336 ckmc_buffer_free(buf);
341 int remove_from_key_manager(const char *pkg_id, wae_app_type_e type)
343 char alias[MAX_ALIAS_LEN] = {0, };
345 _get_alias(pkg_id, type, true, alias, sizeof(alias));
347 return _to_wae_error(ckmc_remove_alias(alias));
350 static void _get_dek_kek_alias(char *alias, size_t buff_len)
352 snprintf(alias, buff_len, "%s%s%s",
353 ckmc_owner_id_system,
354 ckmc_owner_id_separator,
358 int get_dek_kek_from_key_manager(raw_buffer_s **pdek_kek)
360 if (pdek_kek == NULL)
361 return WAE_ERROR_INVALID_PARAMETER;
363 ckmc_raw_buffer_s *buf = NULL;
365 char alias[MAX_ALIAS_LEN] = {0, };
366 _get_dek_kek_alias(alias, sizeof(alias));
368 int ret = _to_wae_error(ckmc_get_data(alias, NULL, &buf));
369 if (ret != WAE_ERROR_NONE) {
370 WAE_SLOGE("Failed to get dek kek from key-manager. alias(%s) ret(%d)",
375 raw_buffer_s *dek_kek = buffer_create(buf->size);
376 if (dek_kek == NULL) {
377 ret = WAE_ERROR_MEMORY;
380 memcpy(dek_kek->buf, buf->data, dek_kek->size);
384 WAE_SLOGI("Success to get dek kek from key-manager.");
387 ckmc_buffer_free(buf);
389 if (ret != WAE_ERROR_NONE)
390 buffer_destroy(dek_kek);