Added Milenage-GSM simulator for EAP-SIM
[mech_eap.git] / src / eap_peer / eap_sim.c
1 /*
2  * EAP peer method: EAP-SIM (RFC 4186)
3  * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16
17 #include "common.h"
18 #include "eap_peer/eap_i.h"
19 #include "eap_config.h"
20 #include "pcsc_funcs.h"
21 #include "eap_common/eap_sim_common.h"
22 #ifdef CONFIG_SIM_SIMULATOR
23 #include "hlr_auc_gw/milenage.h"
24 #endif /* CONFIG_SIM_SIMULATOR */
25
26
27 struct eap_sim_data {
28         u8 *ver_list;
29         size_t ver_list_len;
30         int selected_version;
31         size_t min_num_chal, num_chal;
32
33         u8 kc[3][EAP_SIM_KC_LEN];
34         u8 sres[3][EAP_SIM_SRES_LEN];
35         u8 nonce_mt[EAP_SIM_NONCE_MT_LEN], nonce_s[EAP_SIM_NONCE_S_LEN];
36         u8 mk[EAP_SIM_MK_LEN];
37         u8 k_aut[EAP_SIM_K_AUT_LEN];
38         u8 k_encr[EAP_SIM_K_ENCR_LEN];
39         u8 msk[EAP_SIM_KEYING_DATA_LEN];
40         u8 emsk[EAP_EMSK_LEN];
41         u8 rand[3][GSM_RAND_LEN];
42
43         int num_id_req, num_notification;
44         u8 *pseudonym;
45         size_t pseudonym_len;
46         u8 *reauth_id;
47         size_t reauth_id_len;
48         int reauth;
49         unsigned int counter, counter_too_small;
50         u8 *last_eap_identity;
51         size_t last_eap_identity_len;
52         enum {
53                 CONTINUE, RESULT_SUCCESS, RESULT_FAILURE, SUCCESS, FAILURE
54         } state;
55         int result_ind, use_result_ind;
56 };
57
58
59 #ifndef CONFIG_NO_STDOUT_DEBUG
60 static const char * eap_sim_state_txt(int state)
61 {
62         switch (state) {
63         case CONTINUE:
64                 return "CONTINUE";
65         case RESULT_SUCCESS:
66                 return "RESULT_SUCCESS";
67         case RESULT_FAILURE:
68                 return "RESULT_FAILURE";
69         case SUCCESS:
70                 return "SUCCESS";
71         case FAILURE:
72                 return "FAILURE";
73         default:
74                 return "?";
75         }
76 }
77 #endif /* CONFIG_NO_STDOUT_DEBUG */
78
79
80 static void eap_sim_state(struct eap_sim_data *data, int state)
81 {
82         wpa_printf(MSG_DEBUG, "EAP-SIM: %s -> %s",
83                    eap_sim_state_txt(data->state),
84                    eap_sim_state_txt(state));
85         data->state = state;
86 }
87
88
89 static void * eap_sim_init(struct eap_sm *sm)
90 {
91         struct eap_sim_data *data;
92         struct eap_peer_config *config = eap_get_config(sm);
93
94         data = os_zalloc(sizeof(*data));
95         if (data == NULL)
96                 return NULL;
97
98         if (os_get_random(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) {
99                 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data "
100                            "for NONCE_MT");
101                 os_free(data);
102                 return NULL;
103         }
104
105         data->min_num_chal = 2;
106         if (config && config->phase1) {
107                 char *pos = os_strstr(config->phase1, "sim_min_num_chal=");
108                 if (pos) {
109                         data->min_num_chal = atoi(pos + 17);
110                         if (data->min_num_chal < 2 || data->min_num_chal > 3) {
111                                 wpa_printf(MSG_WARNING, "EAP-SIM: Invalid "
112                                            "sim_min_num_chal configuration "
113                                            "(%lu, expected 2 or 3)",
114                                            (unsigned long) data->min_num_chal);
115                                 os_free(data);
116                                 return NULL;
117                         }
118                         wpa_printf(MSG_DEBUG, "EAP-SIM: Set minimum number of "
119                                    "challenges to %lu",
120                                    (unsigned long) data->min_num_chal);
121                 }
122
123                 data->result_ind = os_strstr(config->phase1, "result_ind=1") !=
124                         NULL;
125         }
126
127         eap_sim_state(data, CONTINUE);
128
129         return data;
130 }
131
132
133 static void eap_sim_deinit(struct eap_sm *sm, void *priv)
134 {
135         struct eap_sim_data *data = priv;
136         if (data) {
137                 os_free(data->ver_list);
138                 os_free(data->pseudonym);
139                 os_free(data->reauth_id);
140                 os_free(data->last_eap_identity);
141                 os_free(data);
142         }
143 }
144
145
146 static int eap_sim_gsm_auth(struct eap_sm *sm, struct eap_sim_data *data)
147 {
148         struct eap_peer_config *conf;
149
150         wpa_printf(MSG_DEBUG, "EAP-SIM: GSM authentication algorithm");
151
152         conf = eap_get_config(sm);
153         if (conf == NULL)
154                 return -1;
155         if (conf->pcsc) {
156                 if (scard_gsm_auth(sm->scard_ctx, data->rand[0],
157                                    data->sres[0], data->kc[0]) ||
158                     scard_gsm_auth(sm->scard_ctx, data->rand[1],
159                                    data->sres[1], data->kc[1]) ||
160                     (data->num_chal > 2 &&
161                      scard_gsm_auth(sm->scard_ctx, data->rand[2],
162                                     data->sres[2], data->kc[2]))) {
163                         wpa_printf(MSG_DEBUG, "EAP-SIM: GSM SIM "
164                                    "authentication could not be completed");
165                         return -1;
166                 }
167                 return 0;
168         }
169
170 #ifdef CONFIG_SIM_SIMULATOR
171         if (conf->password) {
172                 u8 opc[16], k[16];
173                 const char *pos;
174                 wpa_printf(MSG_DEBUG, "EAP-SIM: Use internal GSM-Milenage "
175                            "implementation for authentication");
176                 if (conf->password_len < 65) {
177                         wpa_printf(MSG_DEBUG, "EAP-SIM: invalid GSM-Milenage "
178                                    "password");
179                         return -1;
180                 }
181                 pos = (const char *) conf->password;
182                 if (hexstr2bin(pos, k, 16))
183                         return -1;
184                 pos += 32;
185                 if (*pos != ':')
186                         return -1;
187                 pos++;
188
189                 if (hexstr2bin(pos, opc, 16))
190                         return -1;
191
192                 if (gsm_milenage(opc, k, data->rand[0],
193                                  data->sres[0], data->kc[0]) ||
194                     gsm_milenage(opc, k, data->rand[1],
195                                  data->sres[1], data->kc[1]) ||
196                     (data->num_chal > 2 &&
197                      gsm_milenage(opc, k, data->rand[2],
198                                   data->sres[2], data->kc[2]))) {
199                         wpa_printf(MSG_DEBUG, "EAP-SIM: GSM-Milenage "
200                                    "authentication could not be completed");
201                         return -1;
202                 }
203                 return 0;
204         }
205 #endif /* CONFIG_SIM_SIMULATOR */
206
207 #ifdef CONFIG_SIM_HARDCODED
208         /* These hardcoded Kc and SRES values are used for testing. RAND to
209          * KC/SREC mapping is very bogus as far as real authentication is
210          * concerned, but it is quite useful for cases where the AS is rotating
211          * the order of pre-configured values. */
212         {
213                 size_t i;
214
215                 wpa_printf(MSG_DEBUG, "EAP-SIM: Use hardcoded Kc and SRES "
216                            "values for testing");
217
218                 for (i = 0; i < data->num_chal; i++) {
219                         if (data->rand[i][0] == 0xaa) {
220                                 os_memcpy(data->kc[i],
221                                           "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7",
222                                           EAP_SIM_KC_LEN);
223                                 os_memcpy(data->sres[i], "\xd1\xd2\xd3\xd4",
224                                           EAP_SIM_SRES_LEN);
225                         } else if (data->rand[i][0] == 0xbb) {
226                                 os_memcpy(data->kc[i],
227                                           "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7",
228                                           EAP_SIM_KC_LEN);
229                                 os_memcpy(data->sres[i], "\xe1\xe2\xe3\xe4",
230                                           EAP_SIM_SRES_LEN);
231                         } else {
232                                 os_memcpy(data->kc[i],
233                                           "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7",
234                                           EAP_SIM_KC_LEN);
235                                 os_memcpy(data->sres[i], "\xf1\xf2\xf3\xf4",
236                                           EAP_SIM_SRES_LEN);
237                         }
238                 }
239         }
240
241         return 0;
242
243 #else /* CONFIG_SIM_HARDCODED */
244
245         wpa_printf(MSG_DEBUG, "EAP-SIM: No GSM authentication algorithm "
246                    "enabled");
247         return -1;
248
249 #endif /* CONFIG_SIM_HARDCODED */
250 }
251
252
253 static int eap_sim_supported_ver(int version)
254 {
255         return version == EAP_SIM_VERSION;
256 }
257
258
259 #define CLEAR_PSEUDONYM 0x01
260 #define CLEAR_REAUTH_ID 0x02
261 #define CLEAR_EAP_ID    0x04
262
263 static void eap_sim_clear_identities(struct eap_sim_data *data, int id)
264 {
265         wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old%s%s%s",
266                    id & CLEAR_PSEUDONYM ? " pseudonym" : "",
267                    id & CLEAR_REAUTH_ID ? " reauth_id" : "",
268                    id & CLEAR_EAP_ID ? " eap_id" : "");
269         if (id & CLEAR_PSEUDONYM) {
270                 os_free(data->pseudonym);
271                 data->pseudonym = NULL;
272                 data->pseudonym_len = 0;
273         }
274         if (id & CLEAR_REAUTH_ID) {
275                 os_free(data->reauth_id);
276                 data->reauth_id = NULL;
277                 data->reauth_id_len = 0;
278         }
279         if (id & CLEAR_EAP_ID) {
280                 os_free(data->last_eap_identity);
281                 data->last_eap_identity = NULL;
282                 data->last_eap_identity_len = 0;
283         }
284 }
285
286
287 static int eap_sim_learn_ids(struct eap_sim_data *data,
288                              struct eap_sim_attrs *attr)
289 {
290         if (attr->next_pseudonym) {
291                 os_free(data->pseudonym);
292                 data->pseudonym = os_malloc(attr->next_pseudonym_len);
293                 if (data->pseudonym == NULL) {
294                         wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for "
295                                    "next pseudonym");
296                         return -1;
297                 }
298                 os_memcpy(data->pseudonym, attr->next_pseudonym,
299                           attr->next_pseudonym_len);
300                 data->pseudonym_len = attr->next_pseudonym_len;
301                 wpa_hexdump_ascii(MSG_DEBUG,
302                                   "EAP-SIM: (encr) AT_NEXT_PSEUDONYM",
303                                   data->pseudonym,
304                                   data->pseudonym_len);
305         }
306
307         if (attr->next_reauth_id) {
308                 os_free(data->reauth_id);
309                 data->reauth_id = os_malloc(attr->next_reauth_id_len);
310                 if (data->reauth_id == NULL) {
311                         wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for "
312                                    "next reauth_id");
313                         return -1;
314                 }
315                 os_memcpy(data->reauth_id, attr->next_reauth_id,
316                           attr->next_reauth_id_len);
317                 data->reauth_id_len = attr->next_reauth_id_len;
318                 wpa_hexdump_ascii(MSG_DEBUG,
319                                   "EAP-SIM: (encr) AT_NEXT_REAUTH_ID",
320                                   data->reauth_id,
321                                   data->reauth_id_len);
322         }
323
324         return 0;
325 }
326
327
328 static struct wpabuf * eap_sim_client_error(struct eap_sim_data *data, u8 id,
329                                             int err)
330 {
331         struct eap_sim_msg *msg;
332
333         eap_sim_state(data, FAILURE);
334         data->num_id_req = 0;
335         data->num_notification = 0;
336
337         msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM,
338                                EAP_SIM_SUBTYPE_CLIENT_ERROR);
339         eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0);
340         return eap_sim_msg_finish(msg, NULL, NULL, 0);
341 }
342
343
344 static struct wpabuf * eap_sim_response_start(struct eap_sm *sm,
345                                               struct eap_sim_data *data, u8 id,
346                                               enum eap_sim_id_req id_req)
347 {
348         const u8 *identity = NULL;
349         size_t identity_len = 0;
350         struct eap_sim_msg *msg;
351
352         data->reauth = 0;
353         if (id_req == ANY_ID && data->reauth_id) {
354                 identity = data->reauth_id;
355                 identity_len = data->reauth_id_len;
356                 data->reauth = 1;
357         } else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) &&
358                    data->pseudonym) {
359                 identity = data->pseudonym;
360                 identity_len = data->pseudonym_len;
361                 eap_sim_clear_identities(data, CLEAR_REAUTH_ID);
362         } else if (id_req != NO_ID_REQ) {
363                 identity = eap_get_config_identity(sm, &identity_len);
364                 if (identity) {
365                         eap_sim_clear_identities(data, CLEAR_PSEUDONYM |
366                                                  CLEAR_REAUTH_ID);
367                 }
368         }
369         if (id_req != NO_ID_REQ)
370                 eap_sim_clear_identities(data, CLEAR_EAP_ID);
371
372         wpa_printf(MSG_DEBUG, "Generating EAP-SIM Start (id=%d)", id);
373         msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id,
374                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START);
375         if (!data->reauth) {
376                 wpa_hexdump(MSG_DEBUG, "   AT_NONCE_MT",
377                             data->nonce_mt, EAP_SIM_NONCE_MT_LEN);
378                 eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_MT, 0,
379                                 data->nonce_mt, EAP_SIM_NONCE_MT_LEN);
380                 wpa_printf(MSG_DEBUG, "   AT_SELECTED_VERSION %d",
381                            data->selected_version);
382                 eap_sim_msg_add(msg, EAP_SIM_AT_SELECTED_VERSION,
383                                 data->selected_version, NULL, 0);
384         }
385
386         if (identity) {
387                 wpa_hexdump_ascii(MSG_DEBUG, "   AT_IDENTITY",
388                                   identity, identity_len);
389                 eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len,
390                                 identity, identity_len);
391         }
392
393         return eap_sim_msg_finish(msg, NULL, NULL, 0);
394 }
395
396
397 static struct wpabuf * eap_sim_response_challenge(struct eap_sim_data *data,
398                                                   u8 id)
399 {
400         struct eap_sim_msg *msg;
401
402         wpa_printf(MSG_DEBUG, "Generating EAP-SIM Challenge (id=%d)", id);
403         msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM,
404                                EAP_SIM_SUBTYPE_CHALLENGE);
405         if (data->use_result_ind) {
406                 wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
407                 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
408         }
409         wpa_printf(MSG_DEBUG, "   AT_MAC");
410         eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
411         return eap_sim_msg_finish(msg, data->k_aut, (u8 *) data->sres,
412                                   data->num_chal * EAP_SIM_SRES_LEN);
413 }
414
415
416 static struct wpabuf * eap_sim_response_reauth(struct eap_sim_data *data,
417                                                u8 id, int counter_too_small)
418 {
419         struct eap_sim_msg *msg;
420         unsigned int counter;
421
422         wpa_printf(MSG_DEBUG, "Generating EAP-SIM Reauthentication (id=%d)",
423                    id);
424         msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM,
425                                EAP_SIM_SUBTYPE_REAUTHENTICATION);
426         wpa_printf(MSG_DEBUG, "   AT_IV");
427         wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
428         eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA);
429
430         if (counter_too_small) {
431                 wpa_printf(MSG_DEBUG, "   *AT_COUNTER_TOO_SMALL");
432                 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0);
433                 counter = data->counter_too_small;
434         } else
435                 counter = data->counter;
436
437         wpa_printf(MSG_DEBUG, "   *AT_COUNTER %d", counter);
438         eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0);
439
440         if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) {
441                 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt "
442                            "AT_ENCR_DATA");
443                 eap_sim_msg_free(msg);
444                 return NULL;
445         }
446         if (data->use_result_ind) {
447                 wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
448                 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
449         }
450         wpa_printf(MSG_DEBUG, "   AT_MAC");
451         eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
452         return eap_sim_msg_finish(msg, data->k_aut, data->nonce_s,
453                                   EAP_SIM_NONCE_S_LEN);
454 }
455
456
457 static struct wpabuf * eap_sim_response_notification(struct eap_sim_data *data,
458                                                      u8 id, u16 notification)
459 {
460         struct eap_sim_msg *msg;
461         u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL;
462
463         wpa_printf(MSG_DEBUG, "Generating EAP-SIM Notification (id=%d)", id);
464         msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id,
465                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION);
466         wpa_printf(MSG_DEBUG, "   AT_NOTIFICATION");
467         eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, notification, NULL, 0);
468         if (k_aut && data->reauth) {
469                 wpa_printf(MSG_DEBUG, "   AT_IV");
470                 wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
471                 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV,
472                                            EAP_SIM_AT_ENCR_DATA);
473                 wpa_printf(MSG_DEBUG, "   *AT_COUNTER %d", data->counter);
474                 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter,
475                                 NULL, 0);
476                 if (eap_sim_msg_add_encr_end(msg, data->k_encr,
477                                              EAP_SIM_AT_PADDING)) {
478                         wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt "
479                                    "AT_ENCR_DATA");
480                         eap_sim_msg_free(msg);
481                         return NULL;
482                 }
483         }
484         if (k_aut) {
485                 wpa_printf(MSG_DEBUG, "   AT_MAC");
486                 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
487         }
488         return eap_sim_msg_finish(msg, k_aut, (u8 *) "", 0);
489 }
490
491
492 static struct wpabuf * eap_sim_process_start(struct eap_sm *sm,
493                                              struct eap_sim_data *data, u8 id,
494                                              struct eap_sim_attrs *attr)
495 {
496         int selected_version = -1, id_error;
497         size_t i;
498         u8 *pos;
499
500         wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Start");
501         if (attr->version_list == NULL) {
502                 wpa_printf(MSG_INFO, "EAP-SIM: No AT_VERSION_LIST in "
503                            "SIM/Start");
504                 return eap_sim_client_error(data, id,
505                                             EAP_SIM_UNSUPPORTED_VERSION);
506         }
507
508         os_free(data->ver_list);
509         data->ver_list = os_malloc(attr->version_list_len);
510         if (data->ver_list == NULL) {
511                 wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to allocate "
512                            "memory for version list");
513                 return eap_sim_client_error(data, id,
514                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
515         }
516         os_memcpy(data->ver_list, attr->version_list, attr->version_list_len);
517         data->ver_list_len = attr->version_list_len;
518         pos = data->ver_list;
519         for (i = 0; i < data->ver_list_len / 2; i++) {
520                 int ver = pos[0] * 256 + pos[1];
521                 pos += 2;
522                 if (eap_sim_supported_ver(ver)) {
523                         selected_version = ver;
524                         break;
525                 }
526         }
527         if (selected_version < 0) {
528                 wpa_printf(MSG_INFO, "EAP-SIM: Could not find a supported "
529                            "version");
530                 return eap_sim_client_error(data, id,
531                                             EAP_SIM_UNSUPPORTED_VERSION);
532         }
533         wpa_printf(MSG_DEBUG, "EAP-SIM: Selected Version %d",
534                    selected_version);
535         data->selected_version = selected_version;
536
537         id_error = 0;
538         switch (attr->id_req) {
539         case NO_ID_REQ:
540                 break;
541         case ANY_ID:
542                 if (data->num_id_req > 0)
543                         id_error++;
544                 data->num_id_req++;
545                 break;
546         case FULLAUTH_ID:
547                 if (data->num_id_req > 1)
548                         id_error++;
549                 data->num_id_req++;
550                 break;
551         case PERMANENT_ID:
552                 if (data->num_id_req > 2)
553                         id_error++;
554                 data->num_id_req++;
555                 break;
556         }
557         if (id_error) {
558                 wpa_printf(MSG_INFO, "EAP-SIM: Too many ID requests "
559                            "used within one authentication");
560                 return eap_sim_client_error(data, id,
561                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
562         }
563
564         return eap_sim_response_start(sm, data, id, attr->id_req);
565 }
566
567
568 static struct wpabuf * eap_sim_process_challenge(struct eap_sm *sm,
569                                                  struct eap_sim_data *data,
570                                                  u8 id,
571                                                  const struct wpabuf *reqData,
572                                                  struct eap_sim_attrs *attr)
573 {
574         const u8 *identity;
575         size_t identity_len;
576         struct eap_sim_attrs eattr;
577
578         wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Challenge");
579         data->reauth = 0;
580         if (!attr->mac || !attr->rand) {
581                 wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message "
582                            "did not include%s%s",
583                            !attr->mac ? " AT_MAC" : "",
584                            !attr->rand ? " AT_RAND" : "");
585                 return eap_sim_client_error(data, id,
586                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
587         }
588
589         wpa_printf(MSG_DEBUG, "EAP-SIM: %lu challenges",
590                    (unsigned long) attr->num_chal);
591         if (attr->num_chal < data->min_num_chal) {
592                 wpa_printf(MSG_INFO, "EAP-SIM: Insufficient number of "
593                            "challenges (%lu)", (unsigned long) attr->num_chal);
594                 return eap_sim_client_error(data, id,
595                                             EAP_SIM_INSUFFICIENT_NUM_OF_CHAL);
596         }
597         if (attr->num_chal > 3) {
598                 wpa_printf(MSG_INFO, "EAP-SIM: Too many challenges "
599                            "(%lu)", (unsigned long) attr->num_chal);
600                 return eap_sim_client_error(data, id,
601                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
602         }
603
604         /* Verify that RANDs are different */
605         if (os_memcmp(attr->rand, attr->rand + GSM_RAND_LEN,
606                    GSM_RAND_LEN) == 0 ||
607             (attr->num_chal > 2 &&
608              (os_memcmp(attr->rand, attr->rand + 2 * GSM_RAND_LEN,
609                         GSM_RAND_LEN) == 0 ||
610               os_memcmp(attr->rand + GSM_RAND_LEN,
611                         attr->rand + 2 * GSM_RAND_LEN,
612                         GSM_RAND_LEN) == 0))) {
613                 wpa_printf(MSG_INFO, "EAP-SIM: Same RAND used multiple times");
614                 return eap_sim_client_error(data, id,
615                                             EAP_SIM_RAND_NOT_FRESH);
616         }
617
618         os_memcpy(data->rand, attr->rand, attr->num_chal * GSM_RAND_LEN);
619         data->num_chal = attr->num_chal;
620                 
621         if (eap_sim_gsm_auth(sm, data)) {
622                 wpa_printf(MSG_WARNING, "EAP-SIM: GSM authentication failed");
623                 return eap_sim_client_error(data, id,
624                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
625         }
626         if (data->last_eap_identity) {
627                 identity = data->last_eap_identity;
628                 identity_len = data->last_eap_identity_len;
629         } else if (data->pseudonym) {
630                 identity = data->pseudonym;
631                 identity_len = data->pseudonym_len;
632         } else
633                 identity = eap_get_config_identity(sm, &identity_len);
634         wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Selected identity for MK "
635                           "derivation", identity, identity_len);
636         eap_sim_derive_mk(identity, identity_len, data->nonce_mt,
637                           data->selected_version, data->ver_list,
638                           data->ver_list_len, data->num_chal,
639                           (const u8 *) data->kc, data->mk);
640         eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk,
641                             data->emsk);
642         if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, data->nonce_mt,
643                                EAP_SIM_NONCE_MT_LEN)) {
644                 wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message "
645                            "used invalid AT_MAC");
646                 return eap_sim_client_error(data, id,
647                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
648         }
649
650         /* Old reauthentication and pseudonym identities must not be used
651          * anymore. In other words, if no new identities are received, full
652          * authentication will be used on next reauthentication. */
653         eap_sim_clear_identities(data, CLEAR_PSEUDONYM | CLEAR_REAUTH_ID |
654                                  CLEAR_EAP_ID);
655
656         if (attr->encr_data) {
657                 u8 *decrypted;
658                 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
659                                                attr->encr_data_len, attr->iv,
660                                                &eattr, 0);
661                 if (decrypted == NULL) {
662                         return eap_sim_client_error(
663                                 data, id, EAP_SIM_UNABLE_TO_PROCESS_PACKET);
664                 }
665                 eap_sim_learn_ids(data, &eattr);
666                 os_free(decrypted);
667         }
668
669         if (data->result_ind && attr->result_ind)
670                 data->use_result_ind = 1;
671
672         if (data->state != FAILURE && data->state != RESULT_FAILURE) {
673                 eap_sim_state(data, data->use_result_ind ?
674                               RESULT_SUCCESS : SUCCESS);
675         }
676
677         data->num_id_req = 0;
678         data->num_notification = 0;
679         /* RFC 4186 specifies that counter is initialized to one after
680          * fullauth, but initializing it to zero makes it easier to implement
681          * reauth verification. */
682         data->counter = 0;
683         return eap_sim_response_challenge(data, id);
684 }
685
686
687 static int eap_sim_process_notification_reauth(struct eap_sim_data *data,
688                                                struct eap_sim_attrs *attr)
689 {
690         struct eap_sim_attrs eattr;
691         u8 *decrypted;
692
693         if (attr->encr_data == NULL || attr->iv == NULL) {
694                 wpa_printf(MSG_WARNING, "EAP-SIM: Notification message after "
695                            "reauth did not include encrypted data");
696                 return -1;
697         }
698
699         decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
700                                        attr->encr_data_len, attr->iv, &eattr,
701                                        0);
702         if (decrypted == NULL) {
703                 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted "
704                            "data from notification message");
705                 return -1;
706         }
707
708         if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) {
709                 wpa_printf(MSG_WARNING, "EAP-SIM: Counter in notification "
710                            "message does not match with counter in reauth "
711                            "message");
712                 os_free(decrypted);
713                 return -1;
714         }
715
716         os_free(decrypted);
717         return 0;
718 }
719
720
721 static int eap_sim_process_notification_auth(struct eap_sim_data *data,
722                                              const struct wpabuf *reqData,
723                                              struct eap_sim_attrs *attr)
724 {
725         if (attr->mac == NULL) {
726                 wpa_printf(MSG_INFO, "EAP-SIM: no AT_MAC in after_auth "
727                            "Notification message");
728                 return -1;
729         }
730
731         if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, (u8 *) "", 0))
732         {
733                 wpa_printf(MSG_WARNING, "EAP-SIM: Notification message "
734                            "used invalid AT_MAC");
735                 return -1;
736         }
737
738         if (data->reauth &&
739             eap_sim_process_notification_reauth(data, attr)) {
740                 wpa_printf(MSG_WARNING, "EAP-SIM: Invalid notification "
741                            "message after reauth");
742                 return -1;
743         }
744
745         return 0;
746 }
747
748
749 static struct wpabuf * eap_sim_process_notification(
750         struct eap_sm *sm, struct eap_sim_data *data, u8 id,
751         const struct wpabuf *reqData, struct eap_sim_attrs *attr)
752 {
753         wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Notification");
754         if (data->num_notification > 0) {
755                 wpa_printf(MSG_INFO, "EAP-SIM: too many notification "
756                            "rounds (only one allowed)");
757                 return eap_sim_client_error(data, id,
758                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
759         }
760         data->num_notification++;
761         if (attr->notification == -1) {
762                 wpa_printf(MSG_INFO, "EAP-SIM: no AT_NOTIFICATION in "
763                            "Notification message");
764                 return eap_sim_client_error(data, id,
765                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
766         }
767
768         if ((attr->notification & 0x4000) == 0 &&
769             eap_sim_process_notification_auth(data, reqData, attr)) {
770                 return eap_sim_client_error(data, id,
771                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
772         }
773
774         eap_sim_report_notification(sm->msg_ctx, attr->notification, 0);
775         if (attr->notification >= 0 && attr->notification < 32768) {
776                 eap_sim_state(data, FAILURE);
777         } else if (attr->notification == EAP_SIM_SUCCESS &&
778                    data->state == RESULT_SUCCESS)
779                 eap_sim_state(data, SUCCESS);
780         return eap_sim_response_notification(data, id, attr->notification);
781 }
782
783
784 static struct wpabuf * eap_sim_process_reauthentication(
785         struct eap_sm *sm, struct eap_sim_data *data, u8 id,
786         const struct wpabuf *reqData, struct eap_sim_attrs *attr)
787 {
788         struct eap_sim_attrs eattr;
789         u8 *decrypted;
790
791         wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Reauthentication");
792
793         if (data->reauth_id == NULL) {
794                 wpa_printf(MSG_WARNING, "EAP-SIM: Server is trying "
795                            "reauthentication, but no reauth_id available");
796                 return eap_sim_client_error(data, id,
797                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
798         }
799
800         data->reauth = 1;
801         if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, (u8 *) "", 0))
802         {
803                 wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication "
804                            "did not have valid AT_MAC");
805                 return eap_sim_client_error(data, id,
806                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
807         }
808
809         if (attr->encr_data == NULL || attr->iv == NULL) {
810                 wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication "
811                            "message did not include encrypted data");
812                 return eap_sim_client_error(data, id,
813                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
814         }
815
816         decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
817                                        attr->encr_data_len, attr->iv, &eattr,
818                                        0);
819         if (decrypted == NULL) {
820                 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted "
821                            "data from reauthentication message");
822                 return eap_sim_client_error(data, id,
823                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
824         }
825
826         if (eattr.nonce_s == NULL || eattr.counter < 0) {
827                 wpa_printf(MSG_INFO, "EAP-SIM: (encr) No%s%s in reauth packet",
828                            !eattr.nonce_s ? " AT_NONCE_S" : "",
829                            eattr.counter < 0 ? " AT_COUNTER" : "");
830                 os_free(decrypted);
831                 return eap_sim_client_error(data, id,
832                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
833         }
834
835         if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) {
836                 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid counter "
837                            "(%d <= %d)", eattr.counter, data->counter);
838                 data->counter_too_small = eattr.counter;
839                 /* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current
840                  * reauth_id must not be used to start a new reauthentication.
841                  * However, since it was used in the last EAP-Response-Identity
842                  * packet, it has to saved for the following fullauth to be
843                  * used in MK derivation. */
844                 os_free(data->last_eap_identity);
845                 data->last_eap_identity = data->reauth_id;
846                 data->last_eap_identity_len = data->reauth_id_len;
847                 data->reauth_id = NULL;
848                 data->reauth_id_len = 0;
849                 os_free(decrypted);
850                 return eap_sim_response_reauth(data, id, 1);
851         }
852         data->counter = eattr.counter;
853
854         os_memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN);
855         wpa_hexdump(MSG_DEBUG, "EAP-SIM: (encr) AT_NONCE_S",
856                     data->nonce_s, EAP_SIM_NONCE_S_LEN);
857
858         eap_sim_derive_keys_reauth(data->counter,
859                                    data->reauth_id, data->reauth_id_len,
860                                    data->nonce_s, data->mk, data->msk,
861                                    data->emsk);
862         eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
863         eap_sim_learn_ids(data, &eattr);
864
865         if (data->result_ind && attr->result_ind)
866                 data->use_result_ind = 1;
867
868         if (data->state != FAILURE && data->state != RESULT_FAILURE) {
869                 eap_sim_state(data, data->use_result_ind ?
870                               RESULT_SUCCESS : SUCCESS);
871         }
872
873         data->num_id_req = 0;
874         data->num_notification = 0;
875         if (data->counter > EAP_SIM_MAX_FAST_REAUTHS) {
876                 wpa_printf(MSG_DEBUG, "EAP-SIM: Maximum number of "
877                            "fast reauths performed - force fullauth");
878                 eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
879         }
880         os_free(decrypted);
881         return eap_sim_response_reauth(data, id, 0);
882 }
883
884
885 static struct wpabuf * eap_sim_process(struct eap_sm *sm, void *priv,
886                                        struct eap_method_ret *ret,
887                                        const struct wpabuf *reqData)
888 {
889         struct eap_sim_data *data = priv;
890         const struct eap_hdr *req;
891         u8 subtype, id;
892         struct wpabuf *res;
893         const u8 *pos;
894         struct eap_sim_attrs attr;
895         size_t len;
896
897         wpa_hexdump_buf(MSG_DEBUG, "EAP-SIM: EAP data", reqData);
898         if (eap_get_config_identity(sm, &len) == NULL) {
899                 wpa_printf(MSG_INFO, "EAP-SIM: Identity not configured");
900                 eap_sm_request_identity(sm);
901                 ret->ignore = TRUE;
902                 return NULL;
903         }
904
905         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, reqData, &len);
906         if (pos == NULL || len < 1) {
907                 ret->ignore = TRUE;
908                 return NULL;
909         }
910         req = wpabuf_head(reqData);
911         id = req->identifier;
912         len = be_to_host16(req->length);
913
914         ret->ignore = FALSE;
915         ret->methodState = METHOD_MAY_CONT;
916         ret->decision = DECISION_FAIL;
917         ret->allowNotifications = TRUE;
918
919         subtype = *pos++;
920         wpa_printf(MSG_DEBUG, "EAP-SIM: Subtype=%d", subtype);
921         pos += 2; /* Reserved */
922
923         if (eap_sim_parse_attr(pos, wpabuf_head_u8(reqData) + len, &attr, 0,
924                                0)) {
925                 res = eap_sim_client_error(data, id,
926                                            EAP_SIM_UNABLE_TO_PROCESS_PACKET);
927                 goto done;
928         }
929
930         switch (subtype) {
931         case EAP_SIM_SUBTYPE_START:
932                 res = eap_sim_process_start(sm, data, id, &attr);
933                 break;
934         case EAP_SIM_SUBTYPE_CHALLENGE:
935                 res = eap_sim_process_challenge(sm, data, id, reqData, &attr);
936                 break;
937         case EAP_SIM_SUBTYPE_NOTIFICATION:
938                 res = eap_sim_process_notification(sm, data, id, reqData,
939                                                    &attr);
940                 break;
941         case EAP_SIM_SUBTYPE_REAUTHENTICATION:
942                 res = eap_sim_process_reauthentication(sm, data, id, reqData,
943                                                        &attr);
944                 break;
945         case EAP_SIM_SUBTYPE_CLIENT_ERROR:
946                 wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Client-Error");
947                 res = eap_sim_client_error(data, id,
948                                            EAP_SIM_UNABLE_TO_PROCESS_PACKET);
949                 break;
950         default:
951                 wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown subtype=%d", subtype);
952                 res = eap_sim_client_error(data, id,
953                                            EAP_SIM_UNABLE_TO_PROCESS_PACKET);
954                 break;
955         }
956
957 done:
958         if (data->state == FAILURE) {
959                 ret->decision = DECISION_FAIL;
960                 ret->methodState = METHOD_DONE;
961         } else if (data->state == SUCCESS) {
962                 ret->decision = data->use_result_ind ?
963                         DECISION_UNCOND_SUCC : DECISION_COND_SUCC;
964                 ret->methodState = data->use_result_ind ?
965                         METHOD_DONE : METHOD_MAY_CONT;
966         } else if (data->state == RESULT_FAILURE)
967                 ret->methodState = METHOD_CONT;
968         else if (data->state == RESULT_SUCCESS)
969                 ret->methodState = METHOD_CONT;
970
971         if (ret->methodState == METHOD_DONE) {
972                 ret->allowNotifications = FALSE;
973         }
974
975         return res;
976 }
977
978
979 static Boolean eap_sim_has_reauth_data(struct eap_sm *sm, void *priv)
980 {
981         struct eap_sim_data *data = priv;
982         return data->pseudonym || data->reauth_id;
983 }
984
985
986 static void eap_sim_deinit_for_reauth(struct eap_sm *sm, void *priv)
987 {
988         struct eap_sim_data *data = priv;
989         eap_sim_clear_identities(data, CLEAR_EAP_ID);
990         data->use_result_ind = 0;
991 }
992
993
994 static void * eap_sim_init_for_reauth(struct eap_sm *sm, void *priv)
995 {
996         struct eap_sim_data *data = priv;
997         if (os_get_random(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) {
998                 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data "
999                            "for NONCE_MT");
1000                 os_free(data);
1001                 return NULL;
1002         }
1003         data->num_id_req = 0;
1004         data->num_notification = 0;
1005         eap_sim_state(data, CONTINUE);
1006         return priv;
1007 }
1008
1009
1010 static const u8 * eap_sim_get_identity(struct eap_sm *sm, void *priv,
1011                                        size_t *len)
1012 {
1013         struct eap_sim_data *data = priv;
1014
1015         if (data->reauth_id) {
1016                 *len = data->reauth_id_len;
1017                 return data->reauth_id;
1018         }
1019
1020         if (data->pseudonym) {
1021                 *len = data->pseudonym_len;
1022                 return data->pseudonym;
1023         }
1024
1025         return NULL;
1026 }
1027
1028
1029 static Boolean eap_sim_isKeyAvailable(struct eap_sm *sm, void *priv)
1030 {
1031         struct eap_sim_data *data = priv;
1032         return data->state == SUCCESS;
1033 }
1034
1035
1036 static u8 * eap_sim_getKey(struct eap_sm *sm, void *priv, size_t *len)
1037 {
1038         struct eap_sim_data *data = priv;
1039         u8 *key;
1040
1041         if (data->state != SUCCESS)
1042                 return NULL;
1043
1044         key = os_malloc(EAP_SIM_KEYING_DATA_LEN);
1045         if (key == NULL)
1046                 return NULL;
1047
1048         *len = EAP_SIM_KEYING_DATA_LEN;
1049         os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN);
1050
1051         return key;
1052 }
1053
1054
1055 static u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
1056 {
1057         struct eap_sim_data *data = priv;
1058         u8 *key;
1059
1060         if (data->state != SUCCESS)
1061                 return NULL;
1062
1063         key = os_malloc(EAP_EMSK_LEN);
1064         if (key == NULL)
1065                 return NULL;
1066
1067         *len = EAP_EMSK_LEN;
1068         os_memcpy(key, data->emsk, EAP_EMSK_LEN);
1069
1070         return key;
1071 }
1072
1073
1074 int eap_peer_sim_register(void)
1075 {
1076         struct eap_method *eap;
1077         int ret;
1078
1079         eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
1080                                     EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM");
1081         if (eap == NULL)
1082                 return -1;
1083
1084         eap->init = eap_sim_init;
1085         eap->deinit = eap_sim_deinit;
1086         eap->process = eap_sim_process;
1087         eap->isKeyAvailable = eap_sim_isKeyAvailable;
1088         eap->getKey = eap_sim_getKey;
1089         eap->has_reauth_data = eap_sim_has_reauth_data;
1090         eap->deinit_for_reauth = eap_sim_deinit_for_reauth;
1091         eap->init_for_reauth = eap_sim_init_for_reauth;
1092         eap->get_identity = eap_sim_get_identity;
1093         eap->get_emsk = eap_sim_get_emsk;
1094
1095         ret = eap_peer_method_register(eap);
1096         if (ret)
1097                 eap_peer_method_free(eap);
1098         return ret;
1099 }