Added wifi formware download for sprd board
[platform/core/connectivity/net-config.git] / src / wifi-eap.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 "log.h"
21 #include "util.h"
22 #include "netdbus.h"
23 #include "neterror.h"
24 #include "wifi-tel-intf.h"
25 #include "network-state.h"
26 #include "wifi-eap.h"
27
28 #define SIM_RAND_DATA_LEN 16
29 #define SIM_AUTH_MAX_RESP_DATA_LEN 128
30 #define SIM_AUTH_SRES_LEN 4
31 #define SIM_AUTH_KC_LEN 8
32
33 #define AKA_RAND_DATA_LEN 16
34 #define AKA_AUTN_DATA_LEN 16
35 #define AKA_AUTH_RES_MAX_LEN 16
36 #define AKA_AUTH_RES_MIN_LEN 4
37 #define AKA_AUTH_CK_LEN 16
38 #define AKA_AUTH_IK_LEN 16
39
40 struct wifii_authentication_data {
41         int auth_result;
42         int resp_length;
43         int authentication_key_length;
44         int cipher_length;
45         int integrity_length;
46         char *resp_data;
47         char *authentication_key;
48         char *cipher_data;
49         char *integrity_data;
50 };
51
52 static struct wifii_authentication_data *wifi_authdata;
53
54 static void *__netconfig_wifi_free_wifi_authdata(
55                 struct wifii_authentication_data *data)
56 {
57         if (data != NULL) {
58                 if (data->resp_data)
59                         g_free(data->resp_data);
60                 if (data->authentication_key)
61                         g_free(data->authentication_key);
62                 if (data->cipher_data)
63                         g_free(data->cipher_data);
64                 if (data->integrity_data)
65                         g_free(data->integrity_data);
66
67                 g_free(data);
68                 data = NULL;
69         }
70
71         return NULL;
72 }
73
74 static void __netconfig_wifi_clean_authentication(void)
75 {
76         netconfig_tel_deinit();
77
78         wifi_authdata = __netconfig_wifi_free_wifi_authdata(wifi_authdata);
79 }
80
81 static gboolean __netconfig_wifi_get_sim_imsi(Wifi *wifi,
82                 GDBusMethodInvocation *context)
83 {
84         int ret;
85         TapiHandle *handle;
86         TelSimImsiInfo_t imsi_info;
87         char *imsi;
88
89         handle = (TapiHandle *)netconfig_tel_init();
90         if (handle == NULL) {
91                 ERR("tapi_init failed");
92                 netconfig_error_fail_get_imsi(context);
93                 return FALSE;
94         }
95
96         ERR("before tel_get_sim_imsi");
97         ret = tel_get_sim_imsi(handle, &imsi_info);
98         ERR("after tel_get_sim_imsi");
99         if (ret != TAPI_API_SUCCESS) {
100                 ERR("Failed tel_get_sim_imsi() : [%d]", ret);
101                 netconfig_error_fail_get_imsi(context);
102                 return FALSE;
103         }
104
105         imsi = g_strdup_printf("%s%s%s", imsi_info.szMcc,
106                         imsi_info.szMnc, imsi_info.szMsin);
107
108         wifi_complete_get_sim_imsi(wifi, context, imsi);
109         g_free(imsi);
110
111         return TRUE;
112 }
113
114 void __netconfig_response_sim_authentication(TapiHandle *handle,
115                 int result, void *data, void *user_data)
116 {
117         if (wifi_authdata != NULL)
118                 wifi_authdata = __netconfig_wifi_free_wifi_authdata(wifi_authdata);
119
120         wifi_authdata = g_try_new0(struct wifii_authentication_data, 1);
121
122         TelSimAuthenticationResponse_t *auth_resp =
123                                 (TelSimAuthenticationResponse_t *) data;
124         if (auth_resp == NULL) {
125                 ERR("the auth response is NULL");
126
127                 wifi_authdata->auth_result = -1;
128                 return;
129         } else
130                 wifi_authdata->auth_result = auth_resp->auth_result;
131
132         if (auth_resp->auth_result == TAPI_SIM_AUTH_NO_ERROR) {
133                 wifi_authdata->resp_length = auth_resp->resp_length;
134                 wifi_authdata->authentication_key_length =
135                                         auth_resp->authentication_key_length;
136
137                 if (wifi_authdata->resp_data != NULL)
138                         g_free(wifi_authdata->resp_data);
139
140                 wifi_authdata->resp_data = g_strdup(auth_resp->resp_data);
141
142                 if (wifi_authdata->authentication_key != NULL)
143                         g_free(wifi_authdata->authentication_key);
144
145                 wifi_authdata->authentication_key =
146                                                         g_strdup(auth_resp->authentication_key);
147         } else {
148                 ERR("the result error for sim auth : [%d]", auth_resp->auth_result);
149
150                 wifi_authdata->resp_length = 0;
151                 wifi_authdata->authentication_key_length = 0;
152         }
153 }
154
155 void __netconfig_response_aka_authentication(TapiHandle *handle,
156                 int result, void *data, void *user_data)
157 {
158         if (wifi_authdata != NULL)
159                 wifi_authdata = __netconfig_wifi_free_wifi_authdata(wifi_authdata);
160
161         wifi_authdata = g_try_new0(struct wifii_authentication_data, 1);
162
163         TelSimAuthenticationResponse_t *auth_resp =
164                                         (TelSimAuthenticationResponse_t *) data;
165         if (auth_resp == NULL) {
166                 ERR("the auth response is NULL");
167
168                 wifi_authdata->auth_result = -1;
169                 return;
170         } else
171                 wifi_authdata->auth_result = auth_resp->auth_result;
172
173         if (auth_resp->auth_result == TAPI_SIM_AUTH_NO_ERROR) {
174                 wifi_authdata->resp_length = auth_resp->resp_length;
175                 wifi_authdata->cipher_length = auth_resp->cipher_length;
176                 wifi_authdata->integrity_length = auth_resp->integrity_length;
177
178                 if (wifi_authdata->resp_data != NULL)
179                         g_free(wifi_authdata->resp_data);
180
181                 wifi_authdata->resp_data = g_strdup(auth_resp->resp_data);
182
183                 if (wifi_authdata->cipher_data != NULL)
184                         g_free(wifi_authdata->cipher_data);
185
186                 wifi_authdata->cipher_data = g_strdup(auth_resp->cipher_data);
187
188                 if (wifi_authdata->integrity_data != NULL)
189                         g_free(wifi_authdata->integrity_data);
190
191                 wifi_authdata->integrity_data = g_strdup(auth_resp->integrity_data);
192         } else {
193                 ERR("the result error for aka auth : [%d]", auth_resp->auth_result);
194
195                 if (auth_resp->auth_result == TAPI_SIM_AUTH_SQN_FAILURE ||
196                                         auth_resp->auth_result == TAPI_SIM_AUTH_SYNCH_FAILURE) {
197                         wifi_authdata->resp_length = auth_resp->resp_length;
198
199                         if (wifi_authdata->resp_data != NULL)
200                                 g_free(wifi_authdata->resp_data);
201
202                         wifi_authdata->resp_data = g_strdup(auth_resp->resp_data);
203                 }
204         }
205 }
206
207 static gboolean __netconfig_wifi_req_sim_auth(GArray *rand_data,
208                 GDBusMethodInvocation *context)
209 {
210         int i;
211         int ret;
212         TapiHandle *handle;
213         TelSimAuthenticationData_t auth_data;
214
215         if (rand_data == NULL)
216                 return FALSE;
217
218         if (rand_data->len != SIM_RAND_DATA_LEN) {
219                 ERR("wrong rand data len : [%d]", rand_data->len);
220
221                 netconfig_error_fail_req_sim_auth_wrong_param(context);
222                 return FALSE;
223         }
224
225         if ((ret = g_array_get_element_size(rand_data)) != 1) {
226                 ERR("wrong rand data size : [%d]", ret);
227
228                 netconfig_error_fail_req_sim_auth_wrong_param(context);
229                 return FALSE;
230         }
231
232         memset(&auth_data, 0, sizeof(auth_data));
233
234         auth_data.auth_type = TAPI_SIM_AUTH_TYPE_GSM;
235         auth_data.rand_length = SIM_RAND_DATA_LEN;
236
237         for (i = 0; i < rand_data->len; i++)
238                 auth_data.rand_data[i] = g_array_index(rand_data, guint8, i);
239
240         handle = (TapiHandle *)netconfig_tel_init();
241         if (handle == NULL) {
242                 netconfig_error_fail_req_sim_auth(context);
243                 return FALSE;
244         }
245
246         ret = tel_req_sim_authentication(handle,
247                         &auth_data, __netconfig_response_sim_authentication, NULL);
248         if (ret != TAPI_API_SUCCESS) {
249                 ERR("Failed tel_req_sim_authentication() : [%d]", ret);
250
251                 netconfig_error_fail_req_sim_auth(context);
252                 return FALSE;
253         }
254
255         return TRUE;
256 }
257
258 static netconfig_error_e __netconfig_wifi_req_aka_auth(
259                 GArray *rand_data, GArray *autn_data, GDBusMethodInvocation *context)
260 {
261         int i;
262         int ret;
263         TapiHandle *handle;
264         TelSimAuthenticationData_t auth_data;
265
266         if (rand_data == NULL || autn_data == NULL)
267                 return NETCONFIG_ERROR_FAILED_REQ_SIM_AUTH;
268
269         if (rand_data->len != AKA_RAND_DATA_LEN) {
270                 ERR("wrong rand data len : [%d]", rand_data->len);
271
272                 return NETCONFIG_ERROR_FAILED_REQ_SIM_AUTH_WRONG_PARAM;
273         }
274
275         if (autn_data->len != AKA_AUTN_DATA_LEN) {
276                 ERR("wrong autn data len : [%d]", autn_data->len);
277
278                 return NETCONFIG_ERROR_FAILED_REQ_SIM_AUTH_WRONG_PARAM;
279         }
280
281         if ((ret = g_array_get_element_size(rand_data)) != 1) {
282                 ERR("wrong rand data size : [%d]", ret);
283
284                 return NETCONFIG_ERROR_FAILED_REQ_SIM_AUTH_WRONG_PARAM;
285         }
286
287         if ((ret = g_array_get_element_size(autn_data)) != 1) {
288                 ERR("wrong autn data size : [%d]", ret);
289
290                 return NETCONFIG_ERROR_FAILED_REQ_SIM_AUTH_WRONG_PARAM;
291         }
292
293         memset(&auth_data, 0, sizeof(auth_data));
294
295         auth_data.auth_type = TAPI_SIM_AUTH_TYPE_3G;
296         auth_data.rand_length = AKA_RAND_DATA_LEN;
297         auth_data.autn_length = AKA_AUTN_DATA_LEN;
298
299         for (i = 0; i < rand_data->len; i++)
300                 auth_data.rand_data[i] = g_array_index(rand_data, guint8, i);
301
302         for (i = 0; i < autn_data->len; i++)
303                 auth_data.autn_data[i] = g_array_index(autn_data, guint8, i);
304
305         handle = (TapiHandle *)netconfig_tel_init();
306         if (handle == NULL)
307                 return NETCONFIG_ERROR_FAILED_REQ_SIM_AUTH;
308
309         ret = tel_req_sim_authentication(handle, &auth_data,
310                         __netconfig_response_aka_authentication, NULL);
311
312         if (ret != TAPI_API_SUCCESS) {
313                 ERR("Failed tel_req_sim_authentication() : [%d]", ret);
314
315                 return NETCONFIG_ERROR_FAILED_REQ_SIM_AUTH;
316         }
317         return NETCONFIG_NO_ERROR;
318 }
319
320 static gboolean __netconfig_wifi_get_sim_authdata(Wifi *wifi,
321                 GDBusMethodInvocation *context)
322 {
323         GArray *array = NULL;
324
325         if (wifi_authdata == NULL) {
326                 DBG("the status error : no response yet");
327                 netconfig_error_fail_get_sim_auth_delay(context);
328                 return FALSE;
329         }
330
331         if (wifi_authdata->auth_result == TAPI_SIM_AUTH_NO_ERROR) {
332                 if (wifi_authdata->resp_length == SIM_AUTH_SRES_LEN &&
333                                 wifi_authdata->authentication_key_length == SIM_AUTH_KC_LEN) {
334                         array = g_array_sized_new(FALSE, FALSE, sizeof(guchar),
335                                         SIM_AUTH_SRES_LEN+SIM_AUTH_KC_LEN);
336                         g_array_append_vals(array, wifi_authdata->resp_data,
337                                         SIM_AUTH_SRES_LEN);
338                         g_array_append_vals(array, wifi_authdata->authentication_key,
339                                         SIM_AUTH_KC_LEN);
340                 } else {
341                         ERR("auth data length is wrong, SRES = [%d], Kc = [%d]",
342                                         wifi_authdata->resp_length,
343                                         wifi_authdata->authentication_key_length);
344                         netconfig_error_fail_get_sim_auth_wrong_data(context);
345                         __netconfig_wifi_clean_authentication();
346                         return FALSE;
347                 }
348         } else {
349                 ERR("failed auth result = [%d]", wifi_authdata->auth_result);
350                 netconfig_error_fail_get_sim_auth_wrong_data(context);
351                 __netconfig_wifi_clean_authentication();
352                 return FALSE;
353         }
354
355         wifi_complete_get_sim_auth(wifi, context, array->data);
356         g_array_free(array, TRUE);
357         __netconfig_wifi_clean_authentication();
358         return TRUE;
359 }
360
361 static gboolean __netconfig_wifi_get_aka_authdata(Wifi *wifi, GDBusMethodInvocation *context)
362 {
363         GArray *array = NULL;
364         guchar res_len;
365
366         if (wifi_authdata == NULL) {
367                 DBG("the status error : no response yet");
368                 netconfig_error_fail_get_sim_auth_delay(context);
369                 return FALSE;
370         }
371
372         switch (wifi_authdata->auth_result) {
373         case TAPI_SIM_AUTH_NO_ERROR:
374                  break;
375
376         case TAPI_SIM_AUTH_SQN_FAILURE:
377         case TAPI_SIM_AUTH_SYNCH_FAILURE:
378                 array = g_array_sized_new(FALSE, FALSE, sizeof(guchar),
379                                                                         wifi_authdata->resp_length+1);
380                 res_len = (guchar)((wifi_authdata->resp_length-1) & 0xff);
381
382                 g_array_append_vals(array, &res_len, 1);
383                 g_array_append_vals(array, wifi_authdata->resp_data,
384                                                                 wifi_authdata->resp_length);
385
386                 wifi_complete_get_aka_auth(wifi, context, array->data);
387                 g_array_free(array, TRUE);
388
389                 __netconfig_wifi_clean_authentication();
390
391                 return TRUE;
392
393         default:
394                 netconfig_error_fail_get_sim_auth_wrong_data(context);
395                 __netconfig_wifi_clean_authentication();
396                 return FALSE;
397         }
398
399         if ((wifi_authdata->resp_length >= AKA_AUTH_RES_MIN_LEN ||
400                         wifi_authdata->resp_length <= AKA_AUTH_RES_MAX_LEN) &&
401                         wifi_authdata->cipher_length == AKA_AUTH_CK_LEN &&
402                         wifi_authdata->integrity_length == AKA_AUTH_IK_LEN) {
403                 array = g_array_sized_new(FALSE, FALSE, sizeof(guchar),
404                                 wifi_authdata->resp_length+AKA_AUTH_CK_LEN+AKA_AUTH_IK_LEN+1);
405
406                 res_len = (guchar)((wifi_authdata->resp_length-1) & 0xff);
407                 g_array_append_vals(array, &res_len, 1);
408                 g_array_append_vals(array, wifi_authdata->resp_data,
409                                                                 wifi_authdata->resp_length);
410                 g_array_append_vals(array, wifi_authdata->cipher_data,
411                                                                 AKA_AUTH_CK_LEN);
412                 g_array_append_vals(array, wifi_authdata->integrity_data,
413                                                                 AKA_AUTH_IK_LEN);
414         } else {
415                 ERR("auth data length is wrong, res = [%d], Kc = [%d], Ki = [%d]",
416                                 wifi_authdata->resp_length, wifi_authdata->cipher_length,
417                                 wifi_authdata->integrity_length);
418
419                 netconfig_error_fail_get_sim_auth_wrong_data(context);
420                 __netconfig_wifi_clean_authentication();
421                 return FALSE;
422         }
423
424         wifi_complete_get_aka_auth(wifi, context, array->data);
425         g_array_free(array, TRUE);
426         __netconfig_wifi_clean_authentication();
427
428         return TRUE;
429 }
430
431 gboolean handle_get_sim_imsi(Wifi *wifi, GDBusMethodInvocation *context)
432 {
433         gboolean ret = TRUE;
434
435         DBG("Get IMSI");
436
437         g_return_val_if_fail(wifi != NULL, FALSE);
438
439         ret = __netconfig_wifi_get_sim_imsi(wifi, context);
440
441         return ret;
442 }
443
444 gboolean handle_req_sim_auth(Wifi *wifi, GDBusMethodInvocation *context, GVariant *rand_data)
445 {
446         gboolean result = TRUE;
447         GArray *rand_data_garray;
448         GVariantIter *iter;
449         gint length;
450         guchar *out_auth_data;
451         guchar byte;
452         int i = 0;
453
454         DBG("Request SIM Authentication");
455
456         g_return_val_if_fail(wifi != NULL, FALSE);
457
458         g_variant_get(rand_data, "ay", &iter);
459         length = g_variant_iter_n_children(iter);
460         out_auth_data = g_new0(guchar, length);
461
462         while (g_variant_iter_loop(iter, "y", &byte)) {
463                 *(out_auth_data + i) = byte;
464                 i++;
465         }
466         g_variant_iter_free(iter);
467
468         rand_data_garray = g_array_sized_new(FALSE, FALSE, sizeof(guchar), length);
469         memcpy(rand_data_garray->data, out_auth_data, length);
470         g_free(out_auth_data);
471         rand_data_garray->len = length;
472
473         result = __netconfig_wifi_req_sim_auth(rand_data_garray, context);
474         g_array_free(rand_data_garray, FALSE);
475
476         if (result)
477                 wifi_complete_req_sim_auth(wifi, context, result);
478
479         return result;
480 }
481
482 gboolean handle_req_aka_auth(Wifi *wifi, GDBusMethodInvocation *context, GVariant *rand_data, GVariant *autn_data)
483 {
484         netconfig_error_e ret = NETCONFIG_NO_ERROR;
485         gboolean result = FALSE;
486         GVariantIter *iter;
487         gint length;
488         guchar *out_auth_data;
489         guchar byte;
490         int i = 0;
491         GArray *rand_data_garray;
492         GArray *autn_data_garray;
493
494         DBG("Request AKA Authentication");
495
496         g_return_val_if_fail(wifi != NULL, FALSE);
497
498         g_variant_get(rand_data, "ay", &iter);
499         length = g_variant_iter_n_children(iter);
500         out_auth_data = g_new0(guchar, length);
501         while (g_variant_iter_loop(iter, "y", &byte)) {
502                 *(out_auth_data + i) = byte;
503                 i++;
504         }
505         g_variant_iter_free(iter);
506
507         rand_data_garray = g_array_sized_new(FALSE, FALSE, sizeof(guchar), length);
508         memcpy(rand_data_garray->data, out_auth_data, length);
509         g_free(out_auth_data);
510         rand_data_garray->len = length;
511
512         i = 0;
513         g_variant_get(autn_data, "ay", &iter);
514         length = g_variant_iter_n_children(iter);
515         out_auth_data = g_new0(guchar, length);
516         while (g_variant_iter_loop(iter, "y", &byte)) {
517                 *(out_auth_data + i) = byte;
518                 i++;
519         }
520         g_variant_iter_free(iter);
521
522         autn_data_garray = g_array_sized_new(FALSE, FALSE, sizeof(guchar), length);
523         memcpy(autn_data_garray->data, out_auth_data, length);
524         g_free(out_auth_data);
525         autn_data_garray->len = length;
526
527         ret = __netconfig_wifi_req_aka_auth(rand_data_garray, autn_data_garray, context);
528         if (ret == NETCONFIG_NO_ERROR) {
529                 result = TRUE;
530                 wifi_complete_req_aka_auth(wifi, context, result);
531         } else if (ret == NETCONFIG_ERROR_FAILED_REQ_SIM_AUTH_WRONG_PARAM) {
532                 netconfig_error_dbus_method_return(context,
533                                 NETCONFIG_ERROR_FAILED_REQ_SIM_AUTH_WRONG_PARAM, "FailReqSimAuthWrongParam");
534         } else {
535                 netconfig_error_dbus_method_return(context,
536                                 NETCONFIG_ERROR_FAILED_REQ_SIM_AUTH, "FailReqSimAuth");
537         }
538
539         g_array_free(rand_data_garray, FALSE);
540         g_array_free(autn_data_garray, FALSE);
541
542         return result;
543 }
544
545 gboolean handle_get_sim_auth(Wifi *wifi, GDBusMethodInvocation *context)
546 {
547         gboolean ret = TRUE;
548
549         DBG("Get SIM Authdata");
550
551         g_return_val_if_fail(wifi != NULL, FALSE);
552
553         ret = __netconfig_wifi_get_sim_authdata(wifi, context);
554         return ret;
555 }
556
557 gboolean handle_get_aka_auth(Wifi *wifi, GDBusMethodInvocation *context)
558 {
559         gboolean ret = TRUE;
560
561         DBG("Get AKA Authdata");
562
563         g_return_val_if_fail(wifi != NULL, FALSE);
564
565         ret = __netconfig_wifi_get_aka_authdata(wifi, context);
566
567         return ret;
568 }