~ubuntu-branches/ubuntu/vivid/wpasupplicant/vivid

« back to all changes in this revision

Viewing changes to eap_sim.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2008-12-02 20:52:16 UTC
  • mfrom: (2.1.30 intrepid)
  • Revision ID: james.westby@ubuntu.com-20081202205216-72fqozu84sdt89a8
Tags: 0.6.4-3
Bugfix: "Missing -d in testing for a directory in init script". 
Thanks to Braun Gábor <braung@renyi.hu> for reporting and the patch.
(Closes: #506328)

Show diffs side-by-side

added added

removed removed

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