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

« back to all changes in this revision

Viewing changes to src/eap_peer/eap_sim.c

  • Committer: Bazaar Package Importer
  • Author(s): Kel Modderman
  • Date: 2008-03-12 20:03:04 UTC
  • mfrom: (1.1.10 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20080312200304-4331y9wj46pdd34z
Tags: 0.6.3-1
* New upstream release.
* Drop patches applied upstream:
  - debian/patches/30_wpa_gui_qt4_eventhistoryui_rework.patch
  - debian/patches/31_wpa_gui_qt4_eventhistory_always_scrollbar.patch
  - debian/patches/32_wpa_gui_qt4_eventhistory_scroll_with_events.patch
  - debian/patches/40_dbus_ssid_data.patch
* Tidy up the clean target of debian/rules. Now that the madwifi headers are
  handled differently we no longer need to do any cleanup.
* Fix formatting error in debian/ifupdown/wpa_action.8 to make lintian
  quieter.
* Add patch to fix formatting errors in manpages build from sgml source. Use
  <emphasis> tags to hightlight keywords instead of surrounding them in
  strong quotes.
  - debian/patches/41_manpage_format_fixes.patch
* wpasupplicant binary package no longer suggests pcscd, guessnet, iproute
  or wireless-tools, nor does it recommend dhcp3-client. These are not
  needed.
* Add debian/patches/10_silence_siocsiwauth_icotl_failure.patch to disable
  ioctl failure messages that occur under normal conditions.
* Cherry pick two upstream git commits concerning the dbus interface:
  - debian/patches/11_avoid_dbus_version_namespace.patch
  - debian/patches/12_fix_potential_use_after_free.patch
* Add debian/patches/42_manpage_explain_available_drivers.patch to explain
  that not all of the driver backends are available in the provided
  wpa_supplicant binary, and that the canonical list of supported driver
  backends can be retrieved from the wpa_supplicant -h (help) output.
  (Closes: #466910)
* Add debian/patches/20_wpa_gui_qt4_disable_link_prl.patch to remove
  link_prl CONFIG compile flag added by qmake-qt4 >= 4.3.4-2 to avoid excess
  linking.

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