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