Add WiFi passphrase encryption routine
[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 void __netconfig_convert_bytes_to_hexstr(char* bin, int blen, gchar* hexstr)
85 {
86         char t;
87
88         while (blen) {
89                 t = (*bin >> 4) & 0x0f;
90
91                 if (t >= 0 && t <= 9)
92                         *hexstr = t + '0';
93                 else if (t >= 10 && t <= 16)
94                         *hexstr = (t - 10) + 'a';
95
96                 hexstr++;
97
98                 t = *bin & 0x0f;
99
100                 if (t >= 0 && t <= 9)
101                         *hexstr = t + '0';
102                 else if (t >= 10 && t <= 16)
103                         *hexstr = (t - 10) + 'a';
104
105                 hexstr++;
106                 bin++;
107                 blen--;
108         }
109
110         *hexstr = '\0';
111 }
112
113 static int __netconfig_generate_aes_key()
114 {
115         ckmc_policy_s pol;
116         pol.extractable = false;
117         pol.password = NULL;
118         int err;
119
120         err = ckmc_create_key_aes(AES_KEY_SIZE, KEY_ALIAS, pol);
121
122         if (err != CKMC_ERROR_NONE && err != CKMC_ERROR_DB_ALIAS_EXISTS)
123                 return err;
124
125         return CKMC_ERROR_NONE;
126 }
127
128 static void*  __netconfig_set_param_list_aes_gcm(ckmc_param_list_h param)
129 {
130         ckmc_raw_buffer_s *iv_buf;
131         unsigned char rnd[RND_LENGTH];
132         ckmc_raw_buffer_s *aad_buf;
133         unsigned char aad[RND_LENGTH];
134
135         err = ckmc_get_data(IV_ALIAS, NULL, &iv_buf);
136
137         if (err == CKMC_ERROR_DB_ALIAS_UNKNOWN) {
138                 ckmc_policy_s policy;
139                 policy.extractable = true;
140                 policy.password = NULL;
141
142                 __netconfig_generate_random_bytes(rnd, RND_LENGTH);
143
144                 CKMC_ERROR_HANDLING(
145                                 ckmc_buffer_new(rnd, RND_LENGTH, &iv_buf),
146                                 NULL);
147
148                 CKMC_ERROR_HANDLING(
149                                 ckmc_save_data(IV_ALIAS, *iv_buf, policy),
150                                 ckmc_buffer_free(iv_buf));
151         }
152
153         err = ckmc_get_data(AAD_ALIAS, NULL, &aad_buf);
154
155         if (err == CKMC_ERROR_DB_ALIAS_UNKNOWN) {
156                 ckmc_policy_s policy;
157                 policy.extractable = true;
158                 policy.password = NULL;
159
160                 __netconfig_generate_random_bytes(aad, RND_LENGTH);
161
162                 CKMC_ERROR_HANDLING(
163                                 ckmc_buffer_new(aad, RND_LENGTH, &aad_buf),
164                                 ckmc_buffer_free(iv_buf));
165
166                 CKMC_ERROR_HANDLING(
167                                 ckmc_save_data(AAD_ALIAS, *aad_buf, policy),
168                                 ckmc_buffer_free(iv_buf);\
169                                 ckmc_buffer_free(aad_buf));
170         }
171
172         CKMC_ERROR_HANDLING(
173                         ckmc_param_list_set_buffer(param, CKMC_PARAM_ED_IV, iv_buf),
174                         ckmc_buffer_free(iv_buf);\
175                         ckmc_buffer_free(aad_buf));
176
177         CKMC_ERROR_HANDLING(
178                         ckmc_param_list_set_buffer(param, CKMC_PARAM_ED_AAD, aad_buf),
179                         ckmc_buffer_free(iv_buf);\
180                         ckmc_buffer_free(aad_buf));
181
182         return GINT_TO_POINTER(1);
183 }
184
185 gchar* _netconfig_encrypt_passphrase(const gchar *passphrase)
186 {
187         gchar* origin_value = NULL;
188         gchar* encrypted_value = NULL;
189
190         ckmc_param_list_h param;
191         ckmc_raw_buffer_s *ptext;
192         ckmc_raw_buffer_s *ctext;
193
194         if (!passphrase)
195                 return NULL;
196
197         origin_value = g_strdup(passphrase);
198
199         CKMC_ERROR_HANDLING(
200                         __netconfig_generate_aes_key(),
201                         g_free(origin_value));
202
203         CKMC_ERROR_HANDLING(
204                         ckmc_generate_new_params(CKMC_ALGO_AES_GCM, &param),
205                         g_free(origin_value));
206
207         if (__netconfig_set_param_list_aes_gcm(param) == NULL) {
208                 g_free(origin_value);
209                 return NULL;
210         }
211
212         CKMC_ERROR_HANDLING(
213                         ckmc_buffer_new((unsigned char*)origin_value,
214                                 strlen((char*)origin_value) + 1, &ptext),
215                         ckmc_param_list_free(param);\
216                         g_free(origin_value));
217
218         CKMC_ERROR_HANDLING(
219                         ckmc_encrypt_data(param, KEY_ALIAS, NULL, *ptext, &ctext),
220                         ckmc_param_list_free(param);\
221                         ckmc_buffer_free(ptext);\
222                         g_free(origin_value));
223
224         if ((encrypted_value = g_try_malloc0(ctext->size * 2 + 1)) == NULL) {
225                 DBG(" encrypted_value allocation failed");
226                 ckmc_param_list_free(param);
227                 ckmc_buffer_free(ptext);
228                 ckmc_buffer_free(ctext);
229                 g_free(origin_value);
230                 return NULL;
231         }
232
233         __netconfig_convert_bytes_to_hexstr((char*)ctext->data, ctext->size, encrypted_value);
234
235         g_free(origin_value);
236
237         ckmc_param_list_free(param);
238         ckmc_buffer_free(ptext);
239         ckmc_buffer_free(ctext);
240
241         return encrypted_value;
242 }
243
244 static gchar* _netconfig_decrypt_passphrase(const gchar *enc_data)
245 {
246         gchar *ehexstr = NULL;
247         gchar *encrypted_value = NULL;
248         gchar *passphrase = NULL;
249
250         ckmc_param_list_h param = NULL;
251         ckmc_raw_buffer_s *ptext;
252         ckmc_raw_buffer_s *ctext;
253
254         if (!enc_data)
255                 return NULL;
256
257         ehexstr = g_strdup(enc_data);
258
259         CKMC_ERROR_HANDLING(
260                         ckmc_generate_new_params(CKMC_ALGO_AES_GCM, &param),
261                         g_free(ehexstr));
262
263         if (__netconfig_set_param_list_aes_gcm(param) == NULL) {
264                 g_free(ehexstr);
265                 return NULL;
266         }
267
268         if ((encrypted_value = g_try_malloc0(strlen((char*)ehexstr)/2)) == NULL) {
269                 DBG(" encrypted_value allocation failed");
270                 ckmc_param_list_free(param);
271                 g_free(ehexstr);
272                 return NULL;
273         }
274
275         __netconfig_convert_hexstr_to_bytes(ehexstr, strlen((char*)ehexstr), encrypted_value);
276
277         CKMC_ERROR_HANDLING(
278                         ckmc_buffer_new((unsigned char*)encrypted_value,
279                                         strlen((char*)ehexstr)/2, &ctext),
280                         ckmc_param_list_free(param);\
281                         g_free(encrypted_value);\
282                         g_free(ehexstr));
283
284         g_free(ehexstr);
285
286         CKMC_ERROR_HANDLING(
287                         ckmc_decrypt_data(param, KEY_ALIAS, NULL, *ctext, &ptext),
288                         ckmc_param_list_free(param);\
289                         ckmc_buffer_free(ctext);\
290                         g_free(encrypted_value));
291
292         passphrase = g_strdup((const gchar*)ptext->data);
293
294         ckmc_param_list_free(param);
295         ckmc_buffer_free(ctext);
296         ckmc_buffer_free(ptext);
297         g_free(encrypted_value);
298
299         return passphrase;
300 }
301
302 gboolean handle_encrypt_passphrase(Wifi *wifi, GDBusMethodInvocation *context, const gchar *passphrase)
303 {
304         gchar *enc_data = NULL;
305
306         if ((wifi == NULL) || (passphrase == NULL)) {
307                 ERR("Invalid parameter");
308                 netconfig_error_invalid_parameter(context);
309                 return FALSE;
310         }
311
312         enc_data = _netconfig_encrypt_passphrase(passphrase);
313
314         if (!enc_data) {
315                 ERR("Failed to encrypt the passphrase");
316                 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "OperationFailed");
317                 return FALSE;
318         }
319
320         wifi_complete_encrypt_passphrase(wifi, context, enc_data);
321         g_free(enc_data);
322
323         return TRUE;
324 }
325
326 gboolean handle_decrypt_passphrase(Wifi *wifi, GDBusMethodInvocation *context, const gchar *enc_data)
327 {
328         gchar *passphrase = NULL;
329
330         if ((wifi == NULL) || (enc_data == NULL)) {
331                 ERR("Invalid parameter");
332                 netconfig_error_invalid_parameter(context);
333                 return FALSE;
334         }
335
336         passphrase = _netconfig_decrypt_passphrase(enc_data);
337
338         if (!passphrase) {
339                 ERR("Failed to decrypt the passphrase");
340                 netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "OperationFailed");
341                 return FALSE;
342         }
343
344         wifi_complete_decrypt_passphrase(wifi, context, passphrase);
345         g_free(passphrase);
346
347         return TRUE;
348 }
349