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

« back to all changes in this revision

Viewing changes to src/eap_peer/eap_aka.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-AKA (RFC 4187)
 
3
 * Copyright (c) 2004-2007, 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 "pcsc_funcs.h"
 
20
#include "eap_common/eap_sim_common.h"
 
21
#include "sha1.h"
 
22
#include "crypto.h"
 
23
 
 
24
 
 
25
struct eap_aka_data {
 
26
        u8 ik[EAP_AKA_IK_LEN], ck[EAP_AKA_CK_LEN], res[EAP_AKA_RES_MAX_LEN];
 
27
        size_t res_len;
 
28
        u8 nonce_s[EAP_SIM_NONCE_S_LEN];
 
29
        u8 mk[EAP_SIM_MK_LEN];
 
30
        u8 k_aut[EAP_SIM_K_AUT_LEN];
 
31
        u8 k_encr[EAP_SIM_K_ENCR_LEN];
 
32
        u8 msk[EAP_SIM_KEYING_DATA_LEN];
 
33
        u8 emsk[EAP_EMSK_LEN];
 
34
        u8 rand[EAP_AKA_RAND_LEN], autn[EAP_AKA_AUTN_LEN];
 
35
        u8 auts[EAP_AKA_AUTS_LEN];
 
36
 
 
37
        int num_id_req, num_notification;
 
38
        u8 *pseudonym;
 
39
        size_t pseudonym_len;
 
40
        u8 *reauth_id;
 
41
        size_t reauth_id_len;
 
42
        int reauth;
 
43
        unsigned int counter, counter_too_small;
 
44
        u8 *last_eap_identity;
 
45
        size_t last_eap_identity_len;
 
46
        enum {
 
47
                CONTINUE, RESULT_SUCCESS, RESULT_FAILURE, SUCCESS, FAILURE
 
48
        } state;
 
49
 
 
50
        struct wpabuf *id_msgs;
 
51
        int prev_id;
 
52
        int result_ind, use_result_ind;
 
53
};
 
54
 
 
55
 
 
56
#ifndef CONFIG_NO_STDOUT_DEBUG
 
57
static const char * eap_aka_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_aka_state(struct eap_aka_data *data, int state)
 
78
{
 
79
        wpa_printf(MSG_DEBUG, "EAP-AKA: %s -> %s",
 
80
                   eap_aka_state_txt(data->state),
 
81
                   eap_aka_state_txt(state));
 
82
        data->state = state;
 
83
}
 
84
 
 
85
 
 
86
static void * eap_aka_init(struct eap_sm *sm)
 
87
{
 
88
        struct eap_aka_data *data;
 
89
        const char *phase1 = eap_get_config_phase1(sm);
 
90
 
 
91
        data = os_zalloc(sizeof(*data));
 
92
        if (data == NULL)
 
93
                return NULL;
 
94
 
 
95
        eap_aka_state(data, CONTINUE);
 
96
        data->prev_id = -1;
 
97
 
 
98
        data->result_ind = phase1 && os_strstr(phase1, "result_ind=1") != NULL;
 
99
 
 
100
        return data;
 
101
}
 
102
 
 
103
 
 
104
static void eap_aka_deinit(struct eap_sm *sm, void *priv)
 
105
{
 
106
        struct eap_aka_data *data = priv;
 
107
        if (data) {
 
108
                os_free(data->pseudonym);
 
109
                os_free(data->reauth_id);
 
110
                os_free(data->last_eap_identity);
 
111
                wpabuf_free(data->id_msgs);
 
112
                os_free(data);
 
113
        }
 
114
}
 
115
 
 
116
 
 
117
static int eap_aka_umts_auth(struct eap_sm *sm, struct eap_aka_data *data)
 
118
{
 
119
        wpa_printf(MSG_DEBUG, "EAP-AKA: UMTS authentication algorithm");
 
120
#ifdef PCSC_FUNCS
 
121
        return scard_umts_auth(sm->scard_ctx, data->rand,
 
122
                               data->autn, data->res, &data->res_len,
 
123
                               data->ik, data->ck, data->auts);
 
124
#else /* PCSC_FUNCS */
 
125
        /* These hardcoded Kc and SRES values are used for testing.
 
126
         * Could consider making them configurable. */
 
127
        os_memset(data->res, '2', EAP_AKA_RES_MAX_LEN);
 
128
        data->res_len = EAP_AKA_RES_MAX_LEN;
 
129
        os_memset(data->ik, '3', EAP_AKA_IK_LEN);
 
130
        os_memset(data->ck, '4', EAP_AKA_CK_LEN);
 
131
        {
 
132
                u8 autn[EAP_AKA_AUTN_LEN];
 
133
                os_memset(autn, '1', EAP_AKA_AUTN_LEN);
 
134
                if (os_memcmp(autn, data->autn, EAP_AKA_AUTN_LEN) != 0) {
 
135
                        wpa_printf(MSG_WARNING, "EAP-AKA: AUTN did not match "
 
136
                                   "with expected value");
 
137
                        return -1;
 
138
                }
 
139
        }
 
140
#if 0
 
141
        {
 
142
                static int test_resync = 1;
 
143
                if (test_resync) {
 
144
                        /* Test Resynchronization */
 
145
                        test_resync = 0;
 
146
                        return -2;
 
147
                }
 
148
        }
 
149
#endif
 
150
        return 0;
 
151
#endif /* PCSC_FUNCS */
 
152
}
 
153
 
 
154
 
 
155
#define CLEAR_PSEUDONYM 0x01
 
156
#define CLEAR_REAUTH_ID 0x02
 
157
#define CLEAR_EAP_ID    0x04
 
158
 
 
159
static void eap_aka_clear_identities(struct eap_aka_data *data, int id)
 
160
{
 
161
        wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old%s%s%s",
 
162
                   id & CLEAR_PSEUDONYM ? " pseudonym" : "",
 
163
                   id & CLEAR_REAUTH_ID ? " reauth_id" : "",
 
164
                   id & CLEAR_EAP_ID ? " eap_id" : "");
 
165
        if (id & CLEAR_PSEUDONYM) {
 
166
                os_free(data->pseudonym);
 
167
                data->pseudonym = NULL;
 
168
                data->pseudonym_len = 0;
 
169
        }
 
170
        if (id & CLEAR_REAUTH_ID) {
 
171
                os_free(data->reauth_id);
 
172
                data->reauth_id = NULL;
 
173
                data->reauth_id_len = 0;
 
174
        }
 
175
        if (id & CLEAR_EAP_ID) {
 
176
                os_free(data->last_eap_identity);
 
177
                data->last_eap_identity = NULL;
 
178
                data->last_eap_identity_len = 0;
 
179
        }
 
180
}
 
181
 
 
182
 
 
183
static int eap_aka_learn_ids(struct eap_aka_data *data,
 
184
                             struct eap_sim_attrs *attr)
 
185
{
 
186
        if (attr->next_pseudonym) {
 
187
                os_free(data->pseudonym);
 
188
                data->pseudonym = os_malloc(attr->next_pseudonym_len);
 
189
                if (data->pseudonym == NULL) {
 
190
                        wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for "
 
191
                                   "next pseudonym");
 
192
                        return -1;
 
193
                }
 
194
                os_memcpy(data->pseudonym, attr->next_pseudonym,
 
195
                          attr->next_pseudonym_len);
 
196
                data->pseudonym_len = attr->next_pseudonym_len;
 
197
                wpa_hexdump_ascii(MSG_DEBUG,
 
198
                                  "EAP-AKA: (encr) AT_NEXT_PSEUDONYM",
 
199
                                  data->pseudonym,
 
200
                                  data->pseudonym_len);
 
201
        }
 
202
 
 
203
        if (attr->next_reauth_id) {
 
204
                os_free(data->reauth_id);
 
205
                data->reauth_id = os_malloc(attr->next_reauth_id_len);
 
206
                if (data->reauth_id == NULL) {
 
207
                        wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for "
 
208
                                   "next reauth_id");
 
209
                        return -1;
 
210
                }
 
211
                os_memcpy(data->reauth_id, attr->next_reauth_id,
 
212
                          attr->next_reauth_id_len);
 
213
                data->reauth_id_len = attr->next_reauth_id_len;
 
214
                wpa_hexdump_ascii(MSG_DEBUG,
 
215
                                  "EAP-AKA: (encr) AT_NEXT_REAUTH_ID",
 
216
                                  data->reauth_id,
 
217
                                  data->reauth_id_len);
 
218
        }
 
219
 
 
220
        return 0;
 
221
}
 
222
 
 
223
 
 
224
static int eap_aka_add_id_msg(struct eap_aka_data *data,
 
225
                              const struct wpabuf *msg)
 
226
{
 
227
        if (msg == NULL)
 
228
                return -1;
 
229
 
 
230
        if (data->id_msgs == NULL) {
 
231
                data->id_msgs = wpabuf_dup(msg);
 
232
                return data->id_msgs == NULL ? -1 : 0;
 
233
        }
 
234
 
 
235
        if (wpabuf_resize(&data->id_msgs, wpabuf_len(msg)) < 0)
 
236
                return -1;
 
237
        wpabuf_put_buf(data->id_msgs, msg);
 
238
 
 
239
        return 0;
 
240
}
 
241
 
 
242
 
 
243
static void eap_aka_add_checkcode(struct eap_aka_data *data,
 
244
                                  struct eap_sim_msg *msg)
 
245
{
 
246
        const u8 *addr;
 
247
        size_t len;
 
248
        u8 hash[SHA1_MAC_LEN];
 
249
 
 
250
        wpa_printf(MSG_DEBUG, "   AT_CHECKCODE");
 
251
 
 
252
        if (data->id_msgs == NULL) {
 
253
                /*
 
254
                 * No EAP-AKA/Identity packets were exchanged - send empty
 
255
                 * checkcode.
 
256
                 */
 
257
                eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, NULL, 0);
 
258
                return;
 
259
        }
 
260
 
 
261
        /* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */
 
262
        addr = wpabuf_head(data->id_msgs);
 
263
        len = wpabuf_len(data->id_msgs);
 
264
        wpa_hexdump(MSG_MSGDUMP, "EAP-AKA: AT_CHECKCODE data", addr, len);
 
265
        sha1_vector(1, &addr, &len, hash);
 
266
 
 
267
        eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, hash,
 
268
                        EAP_AKA_CHECKCODE_LEN);
 
269
}
 
270
 
 
271
 
 
272
static int eap_aka_verify_checkcode(struct eap_aka_data *data,
 
273
                                    const u8 *checkcode, size_t checkcode_len)
 
274
{
 
275
        const u8 *addr;
 
276
        size_t len;
 
277
        u8 hash[SHA1_MAC_LEN];
 
278
 
 
279
        if (checkcode == NULL)
 
280
                return -1;
 
281
 
 
282
        if (data->id_msgs == NULL) {
 
283
                if (checkcode_len != 0) {
 
284
                        wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from server "
 
285
                                   "indicates that AKA/Identity messages were "
 
286
                                   "used, but they were not");
 
287
                        return -1;
 
288
                }
 
289
                return 0;
 
290
        }
 
291
 
 
292
        if (checkcode_len != EAP_AKA_CHECKCODE_LEN) {
 
293
                wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from server "
 
294
                           "indicates that AKA/Identity message were not "
 
295
                           "used, but they were");
 
296
                return -1;
 
297
        }
 
298
 
 
299
        /* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */
 
300
        addr = wpabuf_head(data->id_msgs);
 
301
        len = wpabuf_len(data->id_msgs);
 
302
        sha1_vector(1, &addr, &len, hash);
 
303
 
 
304
        if (os_memcmp(hash, checkcode, EAP_AKA_CHECKCODE_LEN) != 0) {
 
305
                wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE");
 
306
                return -1;
 
307
        }
 
308
 
 
309
        return 0;
 
310
}
 
311
 
 
312
 
 
313
static struct wpabuf * eap_aka_client_error(struct eap_aka_data *data, u8 id,
 
314
                                            int err)
 
315
{
 
316
        struct eap_sim_msg *msg;
 
317
 
 
318
        eap_aka_state(data, FAILURE);
 
319
        data->num_id_req = 0;
 
320
        data->num_notification = 0;
 
321
 
 
322
        msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_AKA,
 
323
                               EAP_AKA_SUBTYPE_CLIENT_ERROR);
 
324
        eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0);
 
325
        return eap_sim_msg_finish(msg, NULL, NULL, 0);
 
326
}
 
327
 
 
328
 
 
329
static struct wpabuf * eap_aka_authentication_reject(struct eap_aka_data *data,
 
330
                                                     u8 id)
 
331
{
 
332
        struct eap_sim_msg *msg;
 
333
 
 
334
        eap_aka_state(data, FAILURE);
 
335
        data->num_id_req = 0;
 
336
        data->num_notification = 0;
 
337
 
 
338
        wpa_printf(MSG_DEBUG, "Generating EAP-AKA Authentication-Reject "
 
339
                   "(id=%d)", id);
 
340
        msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_AKA,
 
341
                               EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT);
 
342
        return eap_sim_msg_finish(msg, NULL, NULL, 0);
 
343
}
 
344
 
 
345
 
 
346
static struct wpabuf * eap_aka_synchronization_failure(
 
347
        struct eap_aka_data *data, u8 id)
 
348
{
 
349
        struct eap_sim_msg *msg;
 
350
 
 
351
        data->num_id_req = 0;
 
352
        data->num_notification = 0;
 
353
 
 
354
        wpa_printf(MSG_DEBUG, "Generating EAP-AKA Synchronization-Failure "
 
355
                   "(id=%d)", id);
 
356
        msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_AKA,
 
357
                               EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE);
 
358
        wpa_printf(MSG_DEBUG, "   AT_AUTS");
 
359
        eap_sim_msg_add_full(msg, EAP_SIM_AT_AUTS, data->auts,
 
360
                             EAP_AKA_AUTS_LEN);
 
361
        return eap_sim_msg_finish(msg, NULL, NULL, 0);
 
362
}
 
363
 
 
364
 
 
365
static struct wpabuf * eap_aka_response_identity(struct eap_sm *sm,
 
366
                                                 struct eap_aka_data *data,
 
367
                                                 u8 id,
 
368
                                                 enum eap_sim_id_req id_req)
 
369
{
 
370
        const u8 *identity = NULL;
 
371
        size_t identity_len = 0;
 
372
        struct eap_sim_msg *msg;
 
373
 
 
374
        data->reauth = 0;
 
375
        if (id_req == ANY_ID && data->reauth_id) {
 
376
                identity = data->reauth_id;
 
377
                identity_len = data->reauth_id_len;
 
378
                data->reauth = 1;
 
379
        } else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) &&
 
380
                   data->pseudonym) {
 
381
                identity = data->pseudonym;
 
382
                identity_len = data->pseudonym_len;
 
383
                eap_aka_clear_identities(data, CLEAR_REAUTH_ID);
 
384
        } else if (id_req != NO_ID_REQ) {
 
385
                identity = eap_get_config_identity(sm, &identity_len);
 
386
                if (identity) {
 
387
                        eap_aka_clear_identities(data, CLEAR_PSEUDONYM |
 
388
                                                 CLEAR_REAUTH_ID);
 
389
                }
 
390
        }
 
391
        if (id_req != NO_ID_REQ)
 
392
                eap_aka_clear_identities(data, CLEAR_EAP_ID);
 
393
 
 
394
        wpa_printf(MSG_DEBUG, "Generating EAP-AKA Identity (id=%d)", id);
 
395
        msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_AKA,
 
396
                               EAP_AKA_SUBTYPE_IDENTITY);
 
397
 
 
398
        if (identity) {
 
399
                wpa_hexdump_ascii(MSG_DEBUG, "   AT_IDENTITY",
 
400
                                  identity, identity_len);
 
401
                eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len,
 
402
                                identity, identity_len);
 
403
        }
 
404
 
 
405
        return eap_sim_msg_finish(msg, NULL, NULL, 0);
 
406
}
 
407
 
 
408
 
 
409
static struct wpabuf * eap_aka_response_challenge(struct eap_aka_data *data,
 
410
                                                  u8 id)
 
411
{
 
412
        struct eap_sim_msg *msg;
 
413
 
 
414
        wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d)", id);
 
415
        msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_AKA,
 
416
                               EAP_AKA_SUBTYPE_CHALLENGE);
 
417
        wpa_printf(MSG_DEBUG, "   AT_RES");
 
418
        eap_sim_msg_add(msg, EAP_SIM_AT_RES, data->res_len,
 
419
                        data->res, data->res_len);
 
420
        eap_aka_add_checkcode(data, msg);
 
421
        if (data->use_result_ind) {
 
422
                wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
 
423
                eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
 
424
        }
 
425
        wpa_printf(MSG_DEBUG, "   AT_MAC");
 
426
        eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
 
427
        return eap_sim_msg_finish(msg, data->k_aut, (u8 *) "", 0);
 
428
}
 
429
 
 
430
 
 
431
static struct wpabuf * eap_aka_response_reauth(struct eap_aka_data *data,
 
432
                                               u8 id, int counter_too_small,
 
433
                                               const u8 *nonce_s)
 
434
{
 
435
        struct eap_sim_msg *msg;
 
436
        unsigned int counter;
 
437
 
 
438
        wpa_printf(MSG_DEBUG, "Generating EAP-AKA Reauthentication (id=%d)",
 
439
                   id);
 
440
        msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_AKA,
 
441
                               EAP_AKA_SUBTYPE_REAUTHENTICATION);
 
442
        wpa_printf(MSG_DEBUG, "   AT_IV");
 
443
        wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
 
444
        eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA);
 
445
 
 
446
        if (counter_too_small) {
 
447
                wpa_printf(MSG_DEBUG, "   *AT_COUNTER_TOO_SMALL");
 
448
                eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0);
 
449
                counter = data->counter_too_small;
 
450
        } else
 
451
                counter = data->counter;
 
452
 
 
453
        wpa_printf(MSG_DEBUG, "   *AT_COUNTER %d", counter);
 
454
        eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0);
 
455
 
 
456
        if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) {
 
457
                wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt "
 
458
                           "AT_ENCR_DATA");
 
459
                eap_sim_msg_free(msg);
 
460
                return NULL;
 
461
        }
 
462
        eap_aka_add_checkcode(data, msg);
 
463
        if (data->use_result_ind) {
 
464
                wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
 
465
                eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
 
466
        }
 
467
        wpa_printf(MSG_DEBUG, "   AT_MAC");
 
468
        eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
 
469
        return eap_sim_msg_finish(msg, data->k_aut, nonce_s,
 
470
                                  EAP_SIM_NONCE_S_LEN);
 
471
}
 
472
 
 
473
 
 
474
static struct wpabuf * eap_aka_response_notification(struct eap_aka_data *data,
 
475
                                                     u8 id, u16 notification)
 
476
{
 
477
        struct eap_sim_msg *msg;
 
478
        u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL;
 
479
 
 
480
        wpa_printf(MSG_DEBUG, "Generating EAP-AKA Notification (id=%d)", id);
 
481
        msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_AKA,
 
482
                               EAP_AKA_SUBTYPE_NOTIFICATION);
 
483
        if (k_aut && data->reauth) {
 
484
                wpa_printf(MSG_DEBUG, "   AT_IV");
 
485
                wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
 
486
                eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV,
 
487
                                           EAP_SIM_AT_ENCR_DATA);
 
488
                wpa_printf(MSG_DEBUG, "   *AT_COUNTER %d", data->counter);
 
489
                eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter,
 
490
                                NULL, 0);
 
491
                if (eap_sim_msg_add_encr_end(msg, data->k_encr,
 
492
                                             EAP_SIM_AT_PADDING)) {
 
493
                        wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt "
 
494
                                   "AT_ENCR_DATA");
 
495
                        eap_sim_msg_free(msg);
 
496
                        return NULL;
 
497
                }
 
498
        }
 
499
        if (k_aut) {
 
500
                wpa_printf(MSG_DEBUG, "   AT_MAC");
 
501
                eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
 
502
        }
 
503
        return eap_sim_msg_finish(msg, k_aut, (u8 *) "", 0);
 
504
}
 
505
 
 
506
 
 
507
static struct wpabuf * eap_aka_process_identity(struct eap_sm *sm,
 
508
                                                struct eap_aka_data *data,
 
509
                                                u8 id,
 
510
                                                const struct wpabuf *reqData,
 
511
                                                struct eap_sim_attrs *attr)
 
512
{
 
513
        int id_error;
 
514
        struct wpabuf *buf;
 
515
 
 
516
        wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Identity");
 
517
 
 
518
        id_error = 0;
 
519
        switch (attr->id_req) {
 
520
        case NO_ID_REQ:
 
521
                break;
 
522
        case ANY_ID:
 
523
                if (data->num_id_req > 0)
 
524
                        id_error++;
 
525
                data->num_id_req++;
 
526
                break;
 
527
        case FULLAUTH_ID:
 
528
                if (data->num_id_req > 1)
 
529
                        id_error++;
 
530
                data->num_id_req++;
 
531
                break;
 
532
        case PERMANENT_ID:
 
533
                if (data->num_id_req > 2)
 
534
                        id_error++;
 
535
                data->num_id_req++;
 
536
                break;
 
537
        }
 
538
        if (id_error) {
 
539
                wpa_printf(MSG_INFO, "EAP-AKA: Too many ID requests "
 
540
                           "used within one authentication");
 
541
                return eap_aka_client_error(data, id,
 
542
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 
543
        }
 
544
 
 
545
        buf = eap_aka_response_identity(sm, data, id, attr->id_req);
 
546
 
 
547
        if (data->prev_id != id) {
 
548
                eap_aka_add_id_msg(data, reqData);
 
549
                eap_aka_add_id_msg(data, buf);
 
550
                data->prev_id = id;
 
551
        }
 
552
 
 
553
        return buf;
 
554
}
 
555
 
 
556
 
 
557
static struct wpabuf * eap_aka_process_challenge(struct eap_sm *sm,
 
558
                                                 struct eap_aka_data *data,
 
559
                                                 u8 id,
 
560
                                                 const struct wpabuf *reqData,
 
561
                                                 struct eap_sim_attrs *attr)
 
562
{
 
563
        const u8 *identity;
 
564
        size_t identity_len;
 
565
        int res;
 
566
        struct eap_sim_attrs eattr;
 
567
 
 
568
        wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Challenge");
 
569
 
 
570
        if (attr->checkcode &&
 
571
            eap_aka_verify_checkcode(data, attr->checkcode,
 
572
                                     attr->checkcode_len)) {
 
573
                wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the "
 
574
                           "message");
 
575
                return eap_aka_client_error(data, id,
 
576
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 
577
        }
 
578
 
 
579
        data->reauth = 0;
 
580
        if (!attr->mac || !attr->rand || !attr->autn) {
 
581
                wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
 
582
                           "did not include%s%s%s",
 
583
                           !attr->mac ? " AT_MAC" : "",
 
584
                           !attr->rand ? " AT_RAND" : "",
 
585
                           !attr->autn ? " AT_AUTN" : "");
 
586
                return eap_aka_client_error(data, id,
 
587
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 
588
        }
 
589
        os_memcpy(data->rand, attr->rand, EAP_AKA_RAND_LEN);
 
590
        os_memcpy(data->autn, attr->autn, EAP_AKA_AUTN_LEN);
 
591
 
 
592
        res = eap_aka_umts_auth(sm, data);
 
593
        if (res == -1) {
 
594
                wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication "
 
595
                           "failed (AUTN)");
 
596
                return eap_aka_authentication_reject(data, id);
 
597
        } else if (res == -2) {
 
598
                wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication "
 
599
                           "failed (AUTN seq# -> AUTS)");
 
600
                return eap_aka_synchronization_failure(data, id);
 
601
        } else if (res) {
 
602
                wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication failed");
 
603
                return eap_aka_client_error(data, id,
 
604
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 
605
        }
 
606
        if (data->last_eap_identity) {
 
607
                identity = data->last_eap_identity;
 
608
                identity_len = data->last_eap_identity_len;
 
609
        } else if (data->pseudonym) {
 
610
                identity = data->pseudonym;
 
611
                identity_len = data->pseudonym_len;
 
612
        } else
 
613
                identity = eap_get_config_identity(sm, &identity_len);
 
614
        wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Selected identity for MK "
 
615
                          "derivation", identity, identity_len);
 
616
        eap_aka_derive_mk(identity, identity_len, data->ik, data->ck,
 
617
                          data->mk);
 
618
        eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk,
 
619
                            data->emsk);
 
620
        if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, (u8 *) "", 0))
 
621
        {
 
622
                wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
 
623
                           "used invalid AT_MAC");
 
624
                return eap_aka_client_error(data, id,
 
625
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 
626
        }
 
627
 
 
628
        /* Old reauthentication and pseudonym identities must not be used
 
629
         * anymore. In other words, if no new identities are received, full
 
630
         * authentication will be used on next reauthentication. */
 
631
        eap_aka_clear_identities(data, CLEAR_PSEUDONYM | CLEAR_REAUTH_ID |
 
632
                                 CLEAR_EAP_ID);
 
633
 
 
634
        if (attr->encr_data) {
 
635
                u8 *decrypted;
 
636
                decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
 
637
                                               attr->encr_data_len, attr->iv,
 
638
                                               &eattr, 0);
 
639
                if (decrypted == NULL) {
 
640
                        return eap_aka_client_error(
 
641
                                data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 
642
                }
 
643
                eap_aka_learn_ids(data, &eattr);
 
644
                os_free(decrypted);
 
645
        }
 
646
 
 
647
        if (data->result_ind && attr->result_ind)
 
648
                data->use_result_ind = 1;
 
649
 
 
650
        if (data->state != FAILURE && data->state != RESULT_FAILURE) {
 
651
                eap_aka_state(data, data->use_result_ind ?
 
652
                              RESULT_SUCCESS : SUCCESS);
 
653
        }
 
654
 
 
655
        data->num_id_req = 0;
 
656
        data->num_notification = 0;
 
657
        /* RFC 4187 specifies that counter is initialized to one after
 
658
         * fullauth, but initializing it to zero makes it easier to implement
 
659
         * reauth verification. */
 
660
        data->counter = 0;
 
661
        return eap_aka_response_challenge(data, id);
 
662
}
 
663
 
 
664
 
 
665
static int eap_aka_process_notification_reauth(struct eap_aka_data *data,
 
666
                                               struct eap_sim_attrs *attr)
 
667
{
 
668
        struct eap_sim_attrs eattr;
 
669
        u8 *decrypted;
 
670
 
 
671
        if (attr->encr_data == NULL || attr->iv == NULL) {
 
672
                wpa_printf(MSG_WARNING, "EAP-AKA: Notification message after "
 
673
                           "reauth did not include encrypted data");
 
674
                return -1;
 
675
        }
 
676
 
 
677
        decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
 
678
                                       attr->encr_data_len, attr->iv, &eattr,
 
679
                                       0);
 
680
        if (decrypted == NULL) {
 
681
                wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
 
682
                           "data from notification message");
 
683
                return -1;
 
684
        }
 
685
 
 
686
        if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) {
 
687
                wpa_printf(MSG_WARNING, "EAP-AKA: Counter in notification "
 
688
                           "message does not match with counter in reauth "
 
689
                           "message");
 
690
                os_free(decrypted);
 
691
                return -1;
 
692
        }
 
693
 
 
694
        os_free(decrypted);
 
695
        return 0;
 
696
}
 
697
 
 
698
 
 
699
static int eap_aka_process_notification_auth(struct eap_aka_data *data,
 
700
                                             const struct wpabuf *reqData,
 
701
                                             struct eap_sim_attrs *attr)
 
702
{
 
703
        if (attr->mac == NULL) {
 
704
                wpa_printf(MSG_INFO, "EAP-AKA: no AT_MAC in after_auth "
 
705
                           "Notification message");
 
706
                return -1;
 
707
        }
 
708
 
 
709
        if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, (u8 *) "", 0))
 
710
        {
 
711
                wpa_printf(MSG_WARNING, "EAP-AKA: Notification message "
 
712
                           "used invalid AT_MAC");
 
713
                return -1;
 
714
        }
 
715
 
 
716
        if (data->reauth &&
 
717
            eap_aka_process_notification_reauth(data, attr)) {
 
718
                wpa_printf(MSG_WARNING, "EAP-AKA: Invalid notification "
 
719
                           "message after reauth");
 
720
                return -1;
 
721
        }
 
722
 
 
723
        return 0;
 
724
}
 
725
 
 
726
 
 
727
static struct wpabuf * eap_aka_process_notification(
 
728
        struct eap_sm *sm, struct eap_aka_data *data, u8 id,
 
729
        const struct wpabuf *reqData, struct eap_sim_attrs *attr)
 
730
{
 
731
        wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Notification");
 
732
        if (data->num_notification > 0) {
 
733
                wpa_printf(MSG_INFO, "EAP-AKA: too many notification "
 
734
                           "rounds (only one allowed)");
 
735
                return eap_aka_client_error(data, id,
 
736
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 
737
        }
 
738
        data->num_notification++;
 
739
        if (attr->notification == -1) {
 
740
                wpa_printf(MSG_INFO, "EAP-AKA: no AT_NOTIFICATION in "
 
741
                           "Notification message");
 
742
                return eap_aka_client_error(data, id,
 
743
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 
744
        }
 
745
 
 
746
        if ((attr->notification & 0x4000) == 0 &&
 
747
            eap_aka_process_notification_auth(data, reqData, attr)) {
 
748
                return eap_aka_client_error(data, id,
 
749
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 
750
        }
 
751
 
 
752
        eap_sim_report_notification(sm->msg_ctx, attr->notification, 1);
 
753
        if (attr->notification >= 0 && attr->notification < 32768) {
 
754
                eap_aka_state(data, FAILURE);
 
755
        } else if (attr->notification == EAP_SIM_SUCCESS &&
 
756
                   data->state == RESULT_SUCCESS)
 
757
                eap_aka_state(data, SUCCESS);
 
758
        return eap_aka_response_notification(data, id, attr->notification);
 
759
}
 
760
 
 
761
 
 
762
static struct wpabuf * eap_aka_process_reauthentication(
 
763
        struct eap_sm *sm, struct eap_aka_data *data, u8 id,
 
764
        const struct wpabuf *reqData, struct eap_sim_attrs *attr)
 
765
{
 
766
        struct eap_sim_attrs eattr;
 
767
        u8 *decrypted;
 
768
 
 
769
        wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Reauthentication");
 
770
 
 
771
        if (attr->checkcode &&
 
772
            eap_aka_verify_checkcode(data, attr->checkcode,
 
773
                                     attr->checkcode_len)) {
 
774
                wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the "
 
775
                           "message");
 
776
                return eap_aka_client_error(data, id,
 
777
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 
778
        }
 
779
 
 
780
        if (data->reauth_id == NULL) {
 
781
                wpa_printf(MSG_WARNING, "EAP-AKA: Server is trying "
 
782
                           "reauthentication, but no reauth_id available");
 
783
                return eap_aka_client_error(data, id,
 
784
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 
785
        }
 
786
 
 
787
        data->reauth = 1;
 
788
        if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, (u8 *) "", 0))
 
789
        {
 
790
                wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
 
791
                           "did not have valid AT_MAC");
 
792
                return eap_aka_client_error(data, id,
 
793
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 
794
        }
 
795
 
 
796
        if (attr->encr_data == NULL || attr->iv == NULL) {
 
797
                wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
 
798
                           "message did not include encrypted data");
 
799
                return eap_aka_client_error(data, id,
 
800
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 
801
        }
 
802
 
 
803
        decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
 
804
                                       attr->encr_data_len, attr->iv, &eattr,
 
805
                                       0);
 
806
        if (decrypted == NULL) {
 
807
                wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
 
808
                           "data from reauthentication message");
 
809
                return eap_aka_client_error(data, id,
 
810
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 
811
        }
 
812
 
 
813
        if (eattr.nonce_s == NULL || eattr.counter < 0) {
 
814
                wpa_printf(MSG_INFO, "EAP-AKA: (encr) No%s%s in reauth packet",
 
815
                           !eattr.nonce_s ? " AT_NONCE_S" : "",
 
816
                           eattr.counter < 0 ? " AT_COUNTER" : "");
 
817
                os_free(decrypted);
 
818
                return eap_aka_client_error(data, id,
 
819
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 
820
        }
 
821
 
 
822
        if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) {
 
823
                struct wpabuf *res;
 
824
                wpa_printf(MSG_INFO, "EAP-AKA: (encr) Invalid counter "
 
825
                           "(%d <= %d)", eattr.counter, data->counter);
 
826
                data->counter_too_small = eattr.counter;
 
827
 
 
828
                eap_sim_derive_keys_reauth(eattr.counter, data->reauth_id,
 
829
                                           data->reauth_id_len, eattr.nonce_s,
 
830
                                           data->mk, NULL, NULL);
 
831
 
 
832
                /* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current
 
833
                 * reauth_id must not be used to start a new reauthentication.
 
834
                 * However, since it was used in the last EAP-Response-Identity
 
835
                 * packet, it has to saved for the following fullauth to be
 
836
                 * used in MK derivation. */
 
837
                os_free(data->last_eap_identity);
 
838
                data->last_eap_identity = data->reauth_id;
 
839
                data->last_eap_identity_len = data->reauth_id_len;
 
840
                data->reauth_id = NULL;
 
841
                data->reauth_id_len = 0;
 
842
 
 
843
                res = eap_aka_response_reauth(data, id, 1, eattr.nonce_s);
 
844
                os_free(decrypted);
 
845
 
 
846
                return res;
 
847
        }
 
848
        data->counter = eattr.counter;
 
849
 
 
850
        os_memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN);
 
851
        wpa_hexdump(MSG_DEBUG, "EAP-AKA: (encr) AT_NONCE_S",
 
852
                    data->nonce_s, EAP_SIM_NONCE_S_LEN);
 
853
 
 
854
        eap_sim_derive_keys_reauth(data->counter,
 
855
                                   data->reauth_id, data->reauth_id_len,
 
856
                                   data->nonce_s, data->mk, data->msk,
 
857
                                   data->emsk);
 
858
        eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
 
859
        eap_aka_learn_ids(data, &eattr);
 
860
 
 
861
        if (data->result_ind && attr->result_ind)
 
862
                data->use_result_ind = 1;
 
863
 
 
864
        if (data->state != FAILURE && data->state != RESULT_FAILURE) {
 
865
                eap_aka_state(data, data->use_result_ind ?
 
866
                              RESULT_SUCCESS : SUCCESS);
 
867
        }
 
868
 
 
869
        data->num_id_req = 0;
 
870
        data->num_notification = 0;
 
871
        if (data->counter > EAP_AKA_MAX_FAST_REAUTHS) {
 
872
                wpa_printf(MSG_DEBUG, "EAP-AKA: Maximum number of "
 
873
                           "fast reauths performed - force fullauth");
 
874
                eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
 
875
        }
 
876
        os_free(decrypted);
 
877
        return eap_aka_response_reauth(data, id, 0, data->nonce_s);
 
878
}
 
879
 
 
880
 
 
881
static struct wpabuf * eap_aka_process(struct eap_sm *sm, void *priv,
 
882
                                       struct eap_method_ret *ret,
 
883
                                       const struct wpabuf *reqData)
 
884
{
 
885
        struct eap_aka_data *data = priv;
 
886
        const struct eap_hdr *req;
 
887
        u8 subtype, id;
 
888
        struct wpabuf *res;
 
889
        const u8 *pos;
 
890
        struct eap_sim_attrs attr;
 
891
        size_t len;
 
892
 
 
893
        wpa_hexdump_buf(MSG_DEBUG, "EAP-AKA: EAP data", reqData);
 
894
        if (eap_get_config_identity(sm, &len) == NULL) {
 
895
                wpa_printf(MSG_INFO, "EAP-AKA: Identity not configured");
 
896
                eap_sm_request_identity(sm);
 
897
                ret->ignore = TRUE;
 
898
                return NULL;
 
899
        }
 
900
 
 
901
        pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_AKA, reqData, &len);
 
902
        if (pos == NULL || len < 1) {
 
903
                ret->ignore = TRUE;
 
904
                return NULL;
 
905
        }
 
906
        req = wpabuf_head(reqData);
 
907
        id = req->identifier;
 
908
        len = be_to_host16(req->length);
 
909
 
 
910
        ret->ignore = FALSE;
 
911
        ret->methodState = METHOD_MAY_CONT;
 
912
        ret->decision = DECISION_FAIL;
 
913
        ret->allowNotifications = TRUE;
 
914
 
 
915
        subtype = *pos++;
 
916
        wpa_printf(MSG_DEBUG, "EAP-AKA: Subtype=%d", subtype);
 
917
        pos += 2; /* Reserved */
 
918
 
 
919
        if (eap_sim_parse_attr(pos, wpabuf_head_u8(reqData) + len, &attr, 1,
 
920
                               0)) {
 
921
                res = eap_aka_client_error(data, id,
 
922
                                           EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 
923
                goto done;
 
924
        }
 
925
 
 
926
        switch (subtype) {
 
927
        case EAP_AKA_SUBTYPE_IDENTITY:
 
928
                res = eap_aka_process_identity(sm, data, id, reqData, &attr);
 
929
                break;
 
930
        case EAP_AKA_SUBTYPE_CHALLENGE:
 
931
                res = eap_aka_process_challenge(sm, data, id, reqData, &attr);
 
932
                break;
 
933
        case EAP_AKA_SUBTYPE_NOTIFICATION:
 
934
                res = eap_aka_process_notification(sm, data, id, reqData,
 
935
                                                   &attr);
 
936
                break;
 
937
        case EAP_AKA_SUBTYPE_REAUTHENTICATION:
 
938
                res = eap_aka_process_reauthentication(sm, data, id, reqData,
 
939
                                                       &attr);
 
940
                break;
 
941
        case EAP_AKA_SUBTYPE_CLIENT_ERROR:
 
942
                wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Client-Error");
 
943
                res = eap_aka_client_error(data, id,
 
944
                                           EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 
945
                break;
 
946
        default:
 
947
                wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown subtype=%d", subtype);
 
948
                res = eap_aka_client_error(data, id,
 
949
                                           EAP_AKA_UNABLE_TO_PROCESS_PACKET);
 
950
                break;
 
951
        }
 
952
 
 
953
done:
 
954
        if (data->state == FAILURE) {
 
955
                ret->decision = DECISION_FAIL;
 
956
                ret->methodState = METHOD_DONE;
 
957
        } else if (data->state == SUCCESS) {
 
958
                ret->decision = data->use_result_ind ?
 
959
                        DECISION_UNCOND_SUCC : DECISION_COND_SUCC;
 
960
                /*
 
961
                 * It is possible for the server to reply with AKA
 
962
                 * Notification, so we must allow the method to continue and
 
963
                 * not only accept EAP-Success at this point.
 
964
                 */
 
965
                ret->methodState = data->use_result_ind ?
 
966
                        METHOD_DONE : METHOD_MAY_CONT;
 
967
        } else if (data->state == RESULT_FAILURE)
 
968
                ret->methodState = METHOD_CONT;
 
969
        else if (data->state == RESULT_SUCCESS)
 
970
                ret->methodState = METHOD_CONT;
 
971
 
 
972
        if (ret->methodState == METHOD_DONE) {
 
973
                ret->allowNotifications = FALSE;
 
974
        }
 
975
 
 
976
        return res;
 
977
}
 
978
 
 
979
 
 
980
static Boolean eap_aka_has_reauth_data(struct eap_sm *sm, void *priv)
 
981
{
 
982
        struct eap_aka_data *data = priv;
 
983
        return data->pseudonym || data->reauth_id;
 
984
}
 
985
 
 
986
 
 
987
static void eap_aka_deinit_for_reauth(struct eap_sm *sm, void *priv)
 
988
{
 
989
        struct eap_aka_data *data = priv;
 
990
        eap_aka_clear_identities(data, CLEAR_EAP_ID);
 
991
        data->prev_id = -1;
 
992
        wpabuf_free(data->id_msgs);
 
993
        data->id_msgs = NULL;
 
994
        data->use_result_ind = 0;
 
995
}
 
996
 
 
997
 
 
998
static void * eap_aka_init_for_reauth(struct eap_sm *sm, void *priv)
 
999
{
 
1000
        struct eap_aka_data *data = priv;
 
1001
        data->num_id_req = 0;
 
1002
        data->num_notification = 0;
 
1003
        eap_aka_state(data, CONTINUE);
 
1004
        return priv;
 
1005
}
 
1006
 
 
1007
 
 
1008
static const u8 * eap_aka_get_identity(struct eap_sm *sm, void *priv,
 
1009
                                       size_t *len)
 
1010
{
 
1011
        struct eap_aka_data *data = priv;
 
1012
 
 
1013
        if (data->reauth_id) {
 
1014
                *len = data->reauth_id_len;
 
1015
                return data->reauth_id;
 
1016
        }
 
1017
 
 
1018
        if (data->pseudonym) {
 
1019
                *len = data->pseudonym_len;
 
1020
                return data->pseudonym;
 
1021
        }
 
1022
 
 
1023
        return NULL;
 
1024
}
 
1025
 
 
1026
 
 
1027
static Boolean eap_aka_isKeyAvailable(struct eap_sm *sm, void *priv)
 
1028
{
 
1029
        struct eap_aka_data *data = priv;
 
1030
        return data->state == SUCCESS;
 
1031
}
 
1032
 
 
1033
 
 
1034
static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len)
 
1035
{
 
1036
        struct eap_aka_data *data = priv;
 
1037
        u8 *key;
 
1038
 
 
1039
        if (data->state != SUCCESS)
 
1040
                return NULL;
 
1041
 
 
1042
        key = os_malloc(EAP_SIM_KEYING_DATA_LEN);
 
1043
        if (key == NULL)
 
1044
                return NULL;
 
1045
 
 
1046
        *len = EAP_SIM_KEYING_DATA_LEN;
 
1047
        os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN);
 
1048
 
 
1049
        return key;
 
1050
}
 
1051
 
 
1052
 
 
1053
static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
 
1054
{
 
1055
        struct eap_aka_data *data = priv;
 
1056
        u8 *key;
 
1057
 
 
1058
        if (data->state != SUCCESS)
 
1059
                return NULL;
 
1060
 
 
1061
        key = os_malloc(EAP_EMSK_LEN);
 
1062
        if (key == NULL)
 
1063
                return NULL;
 
1064
 
 
1065
        *len = EAP_EMSK_LEN;
 
1066
        os_memcpy(key, data->emsk, EAP_EMSK_LEN);
 
1067
 
 
1068
        return key;
 
1069
}
 
1070
 
 
1071
 
 
1072
int eap_peer_aka_register(void)
 
1073
{
 
1074
        struct eap_method *eap;
 
1075
        int ret;
 
1076
 
 
1077
        eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
 
1078
                                    EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA");
 
1079
        if (eap == NULL)
 
1080
                return -1;
 
1081
 
 
1082
        eap->init = eap_aka_init;
 
1083
        eap->deinit = eap_aka_deinit;
 
1084
        eap->process = eap_aka_process;
 
1085
        eap->isKeyAvailable = eap_aka_isKeyAvailable;
 
1086
        eap->getKey = eap_aka_getKey;
 
1087
        eap->has_reauth_data = eap_aka_has_reauth_data;
 
1088
        eap->deinit_for_reauth = eap_aka_deinit_for_reauth;
 
1089
        eap->init_for_reauth = eap_aka_init_for_reauth;
 
1090
        eap->get_identity = eap_aka_get_identity;
 
1091
        eap->get_emsk = eap_aka_get_emsk;
 
1092
 
 
1093
        ret = eap_peer_method_register(eap);
 
1094
        if (ret)
 
1095
                eap_peer_method_free(eap);
 
1096
        return ret;
 
1097
}