Add data structures
[platform/core/security/libwebappenc.git] / srcs / key_manager.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_manager.c
18  * @author      Kyungwook Tak
19  * @version     1.0
20  * @brief       Serialize/deserialize crypto element and save/get to key-manager
21  */
22 #include "key_manager.h"
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27
28 #include <ckmc/ckmc-manager.h>
29
30 #include "wae_log.h"
31
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"
36
37 static int _to_wae_error(int key_manager_error)
38 {
39         switch (key_manager_error) {
40         case CKMC_ERROR_NONE:
41                 return WAE_ERROR_NONE;
42
43         case CKMC_ERROR_INVALID_PARAMETER:
44                 return WAE_ERROR_INVALID_PARAMETER;
45
46         case CKMC_ERROR_PERMISSION_DENIED:
47                 return WAE_ERROR_PERMISSION_DENIED;
48
49         case CKMC_ERROR_DB_ALIAS_UNKNOWN:
50                 return WAE_ERROR_NO_KEY;
51
52         case CKMC_ERROR_DB_ALIAS_EXISTS:
53                 return WAE_ERROR_KEY_EXISTS;
54
55         case CKMC_ERROR_OUT_OF_MEMORY:
56                 return WAE_ERROR_MEMORY;
57
58         default:
59                 return WAE_ERROR_KEY_MANAGER;
60         }
61 }
62
63 static int _serialize(const crypto_element_s *ce, ckmc_raw_buffer_s **pbuf)
64 {
65         if (!is_crypto_element_valid(ce) || pbuf == NULL)
66                 return WAE_ERROR_INVALID_PARAMETER;
67
68         size_t total_len = sizeof(size_t) * 3 + ce->dek->size + ce->iv->size + sizeof(bool);
69
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);
72
73         unsigned char *_buf = (unsigned char *)malloc(total_len);
74         if (_buf == NULL)
75                 return WAE_ERROR_MEMORY;
76
77         ckmc_raw_buffer_s *buf = NULL;
78         int ret = _to_wae_error(ckmc_buffer_new(_buf, total_len, &buf));
79
80         free(_buf);
81
82         if (ret != WAE_ERROR_NONE)
83                 return ret;
84
85         size_t pos = 0;
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);
91         pos += 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);
95         pos += ce->iv->size;
96         memcpy(buf->data + pos, &ce->is_migrated_app, sizeof(bool));
97         pos += sizeof(bool);
98
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;
104         }
105
106         *pbuf = buf;
107
108         WAE_SLOGD("(serialization) success!");
109
110         return WAE_ERROR_NONE;
111 }
112
113 static int _deserialize(const ckmc_raw_buffer_s *buf, crypto_element_s **pce)
114 {
115         if (buf == NULL || buf->data == NULL || buf->size == 0 || pce == NULL)
116                 return WAE_ERROR_INVALID_PARAMETER;
117
118         size_t dek_size = 0;
119         size_t iv_size = 0;
120         bool is_migrated_app = false;
121         size_t pos = 0;
122         size_t total_len = 0;
123         crypto_element_s *ce = NULL;
124
125         memcpy(&total_len, buf->data, sizeof(size_t));
126         pos += sizeof(size_t);
127
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;
132         }
133
134         // deserialize dek size
135         memcpy(&dek_size, buf->data + pos, sizeof(size_t));
136         pos += sizeof(size_t);
137
138         raw_buffer_s *dek = buffer_create(dek_size);
139         if (dek == NULL)
140                 return WAE_ERROR_MEMORY;
141
142         // deserialize dek
143         memcpy(dek->buf, buf->data + pos, dek->size);
144         pos += dek->size;
145
146         // deserialize iv size
147         memcpy(&iv_size, buf->data + pos, sizeof(size_t));
148         pos += sizeof(size_t);
149
150         raw_buffer_s *iv = buffer_create(iv_size);
151         int ret = WAE_ERROR_NONE;
152         if (iv == NULL) {
153                 ret = WAE_ERROR_MEMORY;
154                 goto error;
155         }
156
157         // deserialize iv
158         memcpy(iv->buf, buf->data + pos, iv->size);
159         pos += iv->size;
160
161         // deserialize is_migrated_app
162         memcpy(&is_migrated_app, buf->data + pos, sizeof(bool));
163         pos += sizeof(bool);
164
165         WAE_SLOGD("(deserialization) total(%d) dek(%d) iv(%d) is_migrated(%d)",
166                           total_len, dek_size, iv_size, is_migrated_app);
167
168         if (pos != buf->size) {
169                 WAE_SLOGE("(deserialization) raw buffer remained after deserializatation done!");
170                 ret = WAE_ERROR_UNKNOWN;
171                 goto error;
172         }
173
174         ce = crypto_element_create(dek, iv);
175         if (ce == NULL) {
176                 ret = WAE_ERROR_MEMORY;
177                 goto error;
178         }
179
180         ce->is_migrated_app = is_migrated_app;
181
182         *pce = ce;
183
184         WAE_SLOGD("(deserialization) success!");
185
186         return WAE_ERROR_NONE;
187
188 error:
189         buffer_destroy(dek);
190         buffer_destroy(iv);
191
192         return ret;
193 }
194
195 static void _get_alias(const char *pkg_id, wae_app_type_e type, bool forSave,
196                                            char *alias, size_t buff_len)
197 {
198         if (type == WAE_DOWNLOADED_NORMAL_APP) {
199                 if (forSave) {
200                         snprintf(alias, buff_len, "%s%s",
201                                          APP_DEK_ALIAS_PFX,
202                                          pkg_id);
203                 } else {
204                         snprintf(alias, buff_len, "%c%s%s%s%s",
205                                         '/', INSTALLER_LABEL,
206                                          ckmc_owner_id_separator,
207                                          APP_DEK_ALIAS_PFX,
208                                          pkg_id);
209                 }
210         } else { // system alias
211                 snprintf(alias, buff_len, "%s%s%s%s",
212                                  ckmc_owner_id_system,
213                                  ckmc_owner_id_separator,
214                                  APP_DEK_ALIAS_PFX,
215                                  pkg_id);
216         }
217 }
218
219 static void _get_dek_loading_done_alias(char *alias, size_t buff_len)
220 {
221         snprintf(alias, buff_len, "%s%s%s",
222                          ckmc_owner_id_system,
223                          ckmc_owner_id_separator,
224                          APP_DEK_LOADING_DONE_ALIAS);
225 }
226
227 bool is_app_deks_loaded_in_key_manager()
228 {
229         char alias[MAX_ALIAS_LEN] = {0, };
230
231         _get_dek_loading_done_alias(alias, sizeof(alias));
232
233         ckmc_raw_buffer_s *buf = NULL;
234         int ret = _to_wae_error(ckmc_get_data(alias, NULL, &buf));
235
236         ckmc_buffer_free(buf);
237
238         switch (ret) {
239         case WAE_ERROR_NONE:
240                 return true;
241         case WAE_ERROR_NO_KEY:
242                 WAE_SLOGI("app dek loading isn't done yet");
243                 return false;
244         default:
245                 WAE_SLOGE("Failed to get dek loading flag data from key-manager. ret(%d)", ret);
246                 return false;
247         }
248 }
249
250 int set_app_deks_loaded_to_key_manager()
251 {
252         unsigned char dummy_data[1] = {0};
253         ckmc_raw_buffer_s buf;
254         buf.data = dummy_data;
255         buf.size = sizeof(dummy_data);
256
257         ckmc_policy_s policy;
258         policy.password = NULL;
259         policy.extractable = true;
260
261         char alias[MAX_ALIAS_LEN] = {0, };
262         _get_dek_loading_done_alias(alias, sizeof(alias));
263
264         int ret = _to_wae_error(ckmc_save_data(alias, buf, policy));
265         if (ret == WAE_ERROR_KEY_EXISTS)
266                 ret = WAE_ERROR_NONE;
267
268         return ret;
269 }
270
271 int clear_app_deks_loaded_from_key_manager()
272 {
273         char alias[MAX_ALIAS_LEN] = {0, };
274         _get_dek_loading_done_alias(alias, sizeof(alias));
275
276         return _to_wae_error(ckmc_remove_alias(alias));
277 }
278
279 int save_to_key_manager(const char *pkg_id, wae_app_type_e type, const crypto_element_s *ce)
280 {
281         char alias[MAX_ALIAS_LEN] = {0, };
282
283         _get_alias(pkg_id, type, true, alias, sizeof(alias));
284
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);
289                 return ret;
290         }
291
292         ckmc_policy_s policy;
293         policy.password = NULL;
294         policy.extractable = true;
295
296         ret = _to_wae_error(ckmc_save_data(alias, *buf, policy));
297
298         ckmc_buffer_free(buf);
299
300         if (ret != WAE_ERROR_NONE) {
301                 WAE_SLOGE("Failed to add crypto element to ckm: pkg_id(%s) alias(%s) ret(%d)",
302                                   pkg_id, alias, ret);
303                 return ret;
304         }
305
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)",
309                                   pkg_id, alias, ret);
310
311                 ckmc_remove_alias(alias); // rollback
312                 return ret;
313         }
314
315         WAE_SLOGI("Success to save crypto element to key-manager. pkg_id(%s)", pkg_id);
316
317         return WAE_ERROR_NONE;
318 }
319
320 int get_from_key_manager(const char *pkg_id, wae_app_type_e type, crypto_element_s **pce)
321 {
322         if (pkg_id == NULL || pce == NULL)
323                 return WAE_ERROR_INVALID_PARAMETER;
324
325         char alias[MAX_ALIAS_LEN] = {0, };
326
327         _get_alias(pkg_id, type, false, alias, sizeof(alias));
328
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)
332                 return ret;
333
334         ret = _deserialize(buf, pce);
335
336         ckmc_buffer_free(buf);
337
338         return ret;
339 }
340
341 int remove_from_key_manager(const char *pkg_id, wae_app_type_e type)
342 {
343         char alias[MAX_ALIAS_LEN] = {0, };
344
345         _get_alias(pkg_id, type, true, alias, sizeof(alias));
346
347         return _to_wae_error(ckmc_remove_alias(alias));
348 }
349
350 static void _get_dek_kek_alias(char *alias, size_t buff_len)
351 {
352         snprintf(alias, buff_len, "%s%s%s",
353                          ckmc_owner_id_system,
354                          ckmc_owner_id_separator,
355                          APP_DEK_KEK_ALIAS);
356 }
357
358 int get_dek_kek_from_key_manager(raw_buffer_s **pdek_kek)
359 {
360         if (pdek_kek == NULL)
361                 return WAE_ERROR_INVALID_PARAMETER;
362
363         ckmc_raw_buffer_s *buf = NULL;
364
365         char alias[MAX_ALIAS_LEN] = {0, };
366         _get_dek_kek_alias(alias, sizeof(alias));
367
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)",
371                                   alias, ret);
372                 return ret;
373         }
374
375         raw_buffer_s *dek_kek = buffer_create(buf->size);
376         if (dek_kek == NULL) {
377                 ret = WAE_ERROR_MEMORY;
378                 goto error;
379         }
380         memcpy(dek_kek->buf, buf->data, dek_kek->size);
381
382         *pdek_kek = dek_kek;
383
384         WAE_SLOGI("Success to get dek kek from key-manager.");
385
386 error:
387         ckmc_buffer_free(buf);
388
389         if (ret != WAE_ERROR_NONE)
390                 buffer_destroy(dek_kek);
391
392         return ret;
393 }