Minor Fix: ip-conflict: set sd to NULL after g_free()
[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;
162         ckmc_raw_buffer_s *ptext;
163         ckmc_raw_buffer_s *ctext;
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 ((encrypted_value = g_try_malloc0(ctext->size * 2 + 1)) == NULL) {
197                 DBG(" encrypted_value allocation failed");
198                 ckmc_param_list_free(param);
199                 ckmc_buffer_free(ptext);
200                 ckmc_buffer_free(ctext);
201                 g_free(origin_value);
202                 return NULL;
203         }
204
205         netconfig_convert_bytes_to_hexstr((const char *)ctext->data, ctext->size, encrypted_value);
206
207         g_free(origin_value);
208
209         ckmc_param_list_free(param);
210         ckmc_buffer_free(ptext);
211         ckmc_buffer_free(ctext);
212
213         return encrypted_value;
214 }
215
216 static gchar* _netconfig_decrypt_passphrase(const gchar *enc_data)
217 {
218         gchar *ehexstr = NULL;
219         gchar *encrypted_value = NULL;
220         gchar *passphrase = NULL;
221
222         ckmc_param_list_h param = NULL;
223         ckmc_raw_buffer_s *ptext;
224         ckmc_raw_buffer_s *ctext;
225
226         if (!enc_data)
227                 return NULL;
228
229         ehexstr = g_strdup(enc_data);
230
231         CKMC_ERROR_HANDLING(
232                         ckmc_generate_new_params(CKMC_ALGO_AES_GCM, &param),
233                         g_free(ehexstr));
234
235         if (__netconfig_set_param_list_aes_gcm(param) == NULL) {
236                 ckmc_param_list_free(param);
237                 g_free(ehexstr);
238                 return NULL;
239         }
240
241         if ((encrypted_value = g_try_malloc0(strlen((char*)ehexstr)/2)) == NULL) {
242                 DBG(" encrypted_value allocation failed");
243                 ckmc_param_list_free(param);
244                 g_free(ehexstr);
245                 return NULL;
246         }
247
248         __netconfig_convert_hexstr_to_bytes(ehexstr, strlen((char*)ehexstr), encrypted_value);
249
250         CKMC_ERROR_HANDLING(
251                         ckmc_buffer_new((unsigned char*)encrypted_value,
252                                         strlen((char*)ehexstr)/2, &ctext),
253                         ckmc_param_list_free(param);\
254                         g_free(encrypted_value);\
255                         g_free(ehexstr));
256
257         g_free(ehexstr);
258
259         CKMC_ERROR_HANDLING(
260                         ckmc_decrypt_data(param, KEY_ALIAS, NULL, *ctext, &ptext),
261                         ckmc_param_list_free(param);\
262                         ckmc_buffer_free(ctext);\
263                         g_free(encrypted_value));
264
265         passphrase = g_strdup((const gchar*)ptext->data);
266
267         ckmc_param_list_free(param);
268         ckmc_buffer_free(ctext);
269         ckmc_buffer_free(ptext);
270         g_free(encrypted_value);
271
272         return passphrase;
273 }
274
275 gboolean handle_encrypt_passphrase(Wifi *wifi, GDBusMethodInvocation *context, const gchar *passphrase)
276 {
277         gchar *enc_data = NULL;
278
279         if ((wifi == NULL) || (passphrase == NULL)) {
280                 ERR("Invalid parameter");
281                 netconfig_error_invalid_parameter(context);
282                 return TRUE;
283         }
284
285         enc_data = _netconfig_encrypt_passphrase(passphrase);
286
287         if (!enc_data) {
288                 ERR("Failed to encrypt the passphrase");
289                 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "OperationFailed");
290                 return TRUE;
291         }
292
293         wifi_complete_encrypt_passphrase(wifi, context, enc_data);
294         g_free(enc_data);
295
296         return TRUE;
297 }
298
299 gboolean handle_decrypt_passphrase(Wifi *wifi, GDBusMethodInvocation *context, const gchar *enc_data)
300 {
301         gchar *passphrase = NULL;
302
303         if ((wifi == NULL) || (enc_data == NULL)) {
304                 ERR("Invalid parameter");
305                 netconfig_error_invalid_parameter(context);
306                 return TRUE;
307         }
308
309         passphrase = _netconfig_decrypt_passphrase(enc_data);
310
311         if (!passphrase) {
312                 ERR("Failed to decrypt the passphrase");
313                 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "OperationFailed");
314                 return TRUE;
315         }
316
317         wifi_complete_decrypt_passphrase(wifi, context, passphrase);
318         g_free(passphrase);
319
320         return TRUE;
321 }
322
323 gboolean handle_decrypt_conf_obj(Wifi *wifi, GDBusMethodInvocation *context,
324                 const gchar *enc_connector,
325                 const gchar *enc_c_sign_key,
326                 const gchar *enc_net_access_key)
327 {
328         GVariantBuilder *builder = NULL;
329         gchar *connector = NULL;
330         gchar *c_sign_key = NULL;
331         gchar *net_access_key = NULL;
332
333         DBG("");
334         if (!wifi || !enc_connector || !enc_c_sign_key || !enc_net_access_key) {
335                 ERR("Invalid parameter");
336                 netconfig_error_invalid_parameter(context);
337                 return TRUE;
338         }
339
340         connector = _netconfig_decrypt_passphrase(enc_connector);
341         c_sign_key = _netconfig_decrypt_passphrase(enc_c_sign_key);
342         net_access_key = _netconfig_decrypt_passphrase(enc_net_access_key);
343
344         if (!connector || !c_sign_key || !net_access_key) {
345                 ERR("Failed to decrypt the configuration object");
346                 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "OperationFailed");
347                 g_free(connector);
348                 g_free(c_sign_key);
349                 g_free(net_access_key);
350                 return TRUE;
351         }
352
353         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
354         g_variant_builder_add(builder, "{sv}", "connector",
355                         g_variant_new_string(connector));
356         g_variant_builder_add(builder, "{sv}", "c_sign_key",
357                         g_variant_new_string(c_sign_key));
358         g_variant_builder_add(builder, "{sv}", "net_access_key",
359                         g_variant_new_string(net_access_key));
360
361         wifi_complete_decrypt_conf_obj(wifi, context, g_variant_builder_end(builder));
362         g_variant_builder_unref(builder);
363         g_free(connector);
364         g_free(c_sign_key);
365         g_free(net_access_key);
366
367         return TRUE;
368 }
369