Use rand_r() instead of rand()
[platform/core/connectivity/net-config.git] / src / wifi-key-encryption.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <stdlib.h>
21 #include <glib.h>
22 #include <ckmc/ckmc-type.h>
23 #include <ckmc/ckmc-manager.h>
24 #include <tizen.h>
25
26 #include "log.h"
27 #include "util.h"
28 #include "wifi-key-encryption.h"
29
30 #define KEY_ALIAS       "connman_wifi_passphrase"
31 #define IV_ALIAS        "connman_wifi_enciv"
32 #define AAD_ALIAS       "connman_wifi_gcmaad"
33
34 #define PASSPHRASE      "Passphrase"
35 #define RND_LENGTH      32
36 #define AES_KEY_SIZE    256
37 #define CKMC_ERROR_HANDLING(expression, release) err = expression; \
38         if (CKMC_ERROR_NONE != err) { \
39                 err_str = get_error_message(err); \
40                 ERR(#expression " : %s", err_str); \
41                 release; \
42                 return NULL; \
43         } \
44         DBG(#expression " success");
45
46 static char* err_str;
47 static int err;
48
49
50 static void __netconfig_generate_random_bytes(unsigned char* bytes, int len)
51 {
52         int i = 0;
53
54         srandom(time(NULL));
55
56         while (len--)
57                 bytes[i++] = (unsigned char)random();
58
59 }
60
61 static void __netconfig_convert_hexstr_to_bytes(gchar* hexstr, int hlen, gchar* bin)
62 {
63         hlen = hlen / 2;
64
65         while (hlen) {
66                 if (*hexstr >= '0' && *hexstr <= '9')
67                         *bin = (*hexstr - '0') << 4;
68                 else if (*hexstr >= 'a' && *hexstr <= 'f')
69                         *bin = (*hexstr - 'a' + 10) << 4;
70
71                 hexstr++;
72
73                 if (*hexstr >= '0' && *hexstr <= '9')
74                         *bin |= (*hexstr - '0') & 0x0f;
75                 else if (*hexstr >= 'a' && *hexstr <= 'f')
76                         *bin |= (*hexstr - 'a' + 10) & 0x0f;
77
78                 hexstr++;
79                 bin++;
80                 hlen--;
81         }
82 }
83
84 static int __netconfig_generate_aes_key()
85 {
86         ckmc_policy_s pol;
87         pol.extractable = false;
88         pol.password = NULL;
89         int err;
90
91         err = ckmc_create_key_aes(AES_KEY_SIZE, KEY_ALIAS, pol);
92
93         if (err != CKMC_ERROR_NONE && err != CKMC_ERROR_DB_ALIAS_EXISTS)
94                 return err;
95
96         return CKMC_ERROR_NONE;
97 }
98
99 static void*  __netconfig_set_param_list_aes_gcm(ckmc_param_list_h param)
100 {
101         ckmc_raw_buffer_s *iv_buf = NULL;
102         unsigned char rnd[RND_LENGTH];
103         ckmc_raw_buffer_s *aad_buf = NULL;
104         unsigned char aad[RND_LENGTH];
105
106         err = ckmc_get_data(IV_ALIAS, NULL, &iv_buf);
107
108         if (err == CKMC_ERROR_DB_ALIAS_UNKNOWN) {
109                 ckmc_policy_s policy;
110                 policy.extractable = true;
111                 policy.password = NULL;
112
113                 __netconfig_generate_random_bytes(rnd, RND_LENGTH);
114
115                 CKMC_ERROR_HANDLING(
116                                 ckmc_buffer_new(rnd, RND_LENGTH, &iv_buf),
117                                 NULL);
118
119                 CKMC_ERROR_HANDLING(
120                                 ckmc_save_data(IV_ALIAS, *iv_buf, policy),
121                                 ckmc_buffer_free(iv_buf));
122         }
123
124         err = ckmc_get_data(AAD_ALIAS, NULL, &aad_buf);
125
126         if (err == CKMC_ERROR_DB_ALIAS_UNKNOWN) {
127                 ckmc_policy_s policy;
128                 policy.extractable = true;
129                 policy.password = NULL;
130
131                 __netconfig_generate_random_bytes(aad, RND_LENGTH);
132
133                 CKMC_ERROR_HANDLING(
134                                 ckmc_buffer_new(aad, RND_LENGTH, &aad_buf),
135                                 ckmc_buffer_free(iv_buf));
136
137                 CKMC_ERROR_HANDLING(
138                                 ckmc_save_data(AAD_ALIAS, *aad_buf, policy),
139                                 ckmc_buffer_free(iv_buf);\
140                                 ckmc_buffer_free(aad_buf));
141         }
142
143         CKMC_ERROR_HANDLING(
144                         ckmc_param_list_set_buffer(param, CKMC_PARAM_ED_IV, iv_buf),
145                         ckmc_buffer_free(iv_buf);\
146                         ckmc_buffer_free(aad_buf));
147
148         CKMC_ERROR_HANDLING(
149                         ckmc_param_list_set_buffer(param, CKMC_PARAM_ED_AAD, aad_buf),
150                         ckmc_buffer_free(iv_buf);\
151                         ckmc_buffer_free(aad_buf));
152
153         return GINT_TO_POINTER(1);
154 }
155
156 gchar* _netconfig_encrypt_passphrase(const gchar *passphrase)
157 {
158         gchar* origin_value = NULL;
159         gchar* encrypted_value = NULL;
160
161         ckmc_param_list_h param = NULL;
162         ckmc_raw_buffer_s *ptext = NULL;
163         ckmc_raw_buffer_s *ctext = NULL;
164
165         if (!passphrase)
166                 return NULL;
167
168         origin_value = g_strdup(passphrase);
169
170         CKMC_ERROR_HANDLING(
171                         __netconfig_generate_aes_key(),
172                         g_free(origin_value));
173
174         CKMC_ERROR_HANDLING(
175                         ckmc_generate_new_params(CKMC_ALGO_AES_GCM, &param),
176                         g_free(origin_value));
177
178         if (__netconfig_set_param_list_aes_gcm(param) == NULL) {
179                 ckmc_param_list_free(param);
180                 g_free(origin_value);
181                 return NULL;
182         }
183
184         CKMC_ERROR_HANDLING(
185                         ckmc_buffer_new((unsigned char*)origin_value,
186                                 strlen((char*)origin_value) + 1, &ptext),
187                         ckmc_param_list_free(param);\
188                         g_free(origin_value));
189
190         CKMC_ERROR_HANDLING(
191                         ckmc_encrypt_data(param, KEY_ALIAS, NULL, *ptext, &ctext),
192                         ckmc_param_list_free(param);\
193                         ckmc_buffer_free(ptext);\
194                         g_free(origin_value));
195
196         if (ctext == NULL ||
197                 (encrypted_value = g_try_malloc0(ctext->size * 2 + 1)) == NULL) {
198                 DBG(" encrypted_value allocation failed");
199                 ckmc_param_list_free(param);
200                 ckmc_buffer_free(ptext);
201                 ckmc_buffer_free(ctext);
202                 g_free(origin_value);
203                 return NULL;
204         }
205
206         netconfig_convert_bytes_to_hexstr((const char *)ctext->data, ctext->size, encrypted_value);
207
208         g_free(origin_value);
209
210         ckmc_param_list_free(param);
211         ckmc_buffer_free(ptext);
212         ckmc_buffer_free(ctext);
213
214         return encrypted_value;
215 }
216
217 static gchar* _netconfig_decrypt_passphrase(const gchar *enc_data)
218 {
219         gchar *ehexstr = NULL;
220         gchar *encrypted_value = NULL;
221         gchar *passphrase = NULL;
222
223         ckmc_param_list_h param = NULL;
224         ckmc_raw_buffer_s *ptext = NULL;
225         ckmc_raw_buffer_s *ctext = NULL;
226
227         if (!enc_data)
228                 return NULL;
229
230         ehexstr = g_strdup(enc_data);
231
232         CKMC_ERROR_HANDLING(
233                         ckmc_generate_new_params(CKMC_ALGO_AES_GCM, &param),
234                         g_free(ehexstr));
235
236         if (__netconfig_set_param_list_aes_gcm(param) == NULL) {
237                 ckmc_param_list_free(param);
238                 g_free(ehexstr);
239                 return NULL;
240         }
241
242         if ((encrypted_value = g_try_malloc0(strlen((char*)ehexstr)/2)) == NULL) {
243                 DBG(" encrypted_value allocation failed");
244                 ckmc_param_list_free(param);
245                 g_free(ehexstr);
246                 return NULL;
247         }
248
249         __netconfig_convert_hexstr_to_bytes(ehexstr, strlen((char*)ehexstr), encrypted_value);
250
251         CKMC_ERROR_HANDLING(
252                         ckmc_buffer_new((unsigned char*)encrypted_value,
253                                         strlen((char*)ehexstr)/2, &ctext),
254                         ckmc_param_list_free(param);\
255                         g_free(encrypted_value);\
256                         g_free(ehexstr));
257
258         g_free(ehexstr);
259
260         CKMC_ERROR_HANDLING(
261                         ckmc_decrypt_data(param, KEY_ALIAS, NULL, *ctext, &ptext),
262                         ckmc_param_list_free(param);\
263                         ckmc_buffer_free(ctext);\
264                         g_free(encrypted_value));
265
266         if (ptext != NULL)
267                 passphrase = g_strdup((const gchar*)ptext->data);
268
269         ckmc_param_list_free(param);
270         ckmc_buffer_free(ctext);
271         ckmc_buffer_free(ptext);
272         g_free(encrypted_value);
273
274         return passphrase;
275 }
276
277 gboolean handle_encrypt_passphrase(Wifi *wifi, GDBusMethodInvocation *context, const gchar *passphrase)
278 {
279         gchar *enc_data = NULL;
280
281         if ((wifi == NULL) || (passphrase == NULL)) {
282                 ERR("Invalid parameter");
283                 netconfig_error_invalid_parameter(context);
284                 return TRUE;
285         }
286
287         enc_data = _netconfig_encrypt_passphrase(passphrase);
288
289         if (!enc_data) {
290                 ERR("Failed to encrypt the passphrase");
291                 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "OperationFailed");
292                 return TRUE;
293         }
294
295         wifi_complete_encrypt_passphrase(wifi, context, enc_data);
296         g_free(enc_data);
297
298         return TRUE;
299 }
300
301 gboolean handle_decrypt_passphrase(Wifi *wifi, GDBusMethodInvocation *context, const gchar *enc_data)
302 {
303         gchar *passphrase = NULL;
304
305         if ((wifi == NULL) || (enc_data == NULL)) {
306                 ERR("Invalid parameter");
307                 netconfig_error_invalid_parameter(context);
308                 return TRUE;
309         }
310
311         passphrase = _netconfig_decrypt_passphrase(enc_data);
312
313         if (!passphrase) {
314                 ERR("Failed to decrypt the passphrase");
315                 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "OperationFailed");
316                 return TRUE;
317         }
318
319         wifi_complete_decrypt_passphrase(wifi, context, passphrase);
320         g_free(passphrase);
321
322         return TRUE;
323 }
324
325 gboolean handle_decrypt_conf_obj(Wifi *wifi, GDBusMethodInvocation *context,
326                 const gchar *enc_connector,
327                 const gchar *enc_c_sign_key,
328                 const gchar *enc_net_access_key)
329 {
330         GVariantBuilder *builder = NULL;
331         gchar *connector = NULL;
332         gchar *c_sign_key = NULL;
333         gchar *net_access_key = NULL;
334
335         DBG("");
336         if (!wifi || !enc_connector || !enc_c_sign_key || !enc_net_access_key) {
337                 ERR("Invalid parameter");
338                 netconfig_error_invalid_parameter(context);
339                 return TRUE;
340         }
341
342         connector = _netconfig_decrypt_passphrase(enc_connector);
343         c_sign_key = _netconfig_decrypt_passphrase(enc_c_sign_key);
344         net_access_key = _netconfig_decrypt_passphrase(enc_net_access_key);
345
346         if (!connector || !c_sign_key || !net_access_key) {
347                 ERR("Failed to decrypt the configuration object");
348                 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "OperationFailed");
349                 g_free(connector);
350                 g_free(c_sign_key);
351                 g_free(net_access_key);
352                 return TRUE;
353         }
354
355         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
356         g_variant_builder_add(builder, "{sv}", "connector",
357                         g_variant_new_string(connector));
358         g_variant_builder_add(builder, "{sv}", "c_sign_key",
359                         g_variant_new_string(c_sign_key));
360         g_variant_builder_add(builder, "{sv}", "net_access_key",
361                         g_variant_new_string(net_access_key));
362
363         wifi_complete_decrypt_conf_obj(wifi, context, g_variant_builder_end(builder));
364         g_variant_builder_unref(builder);
365         g_free(connector);
366         g_free(c_sign_key);
367         g_free(net_access_key);
368
369         return TRUE;
370 }
371