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