~ubuntu-branches/ubuntu/oneiric/wpasupplicant/oneiric

« back to all changes in this revision

Viewing changes to eap_aka.c

  • Committer: Bazaar Package Importer
  • Author(s): Kel Modderman
  • Date: 2006-10-05 08:04:01 UTC
  • mfrom: (1.2.1 upstream) (2.1.14 edgy)
  • Revision ID: james.westby@ubuntu.com-20061005080401-myfwjtq7di70dyeo
* Update madwifi headers to latest SVN. (Closes: #388316)
* Remove failed attempt at action locking. [debian/functions.sh,
  debian/wpa_action.sh]
* Add hysteresis checking functions, to avoid "event loops" while
  using wpa-roam. [debian/functions.sh, debian/wpa_action.sh]
* Change of co-maintainer email address.
* Add ishex() function to functions.sh to determine wpa-psk value type in
  plaintext or hex. This effectively eliminates the need for the bogus and
  somewhat confusing wpa-passphrase contruct specific to our scripts and
  allows wpa-psk to work with either a 8 to 63 character long plaintext
  string or 64 character long hex string.
* Adjust README.modes to not refer to the redundant wpa-passphrase stuff.
* Add big fat NOTE about acceptable wpa-psk's to top of example gallery.
* Strip surrounding quotes from wpa-ssid if present, instead of just whining
  about them.
* Update email address in copyright blurb of functions.sh, ifupdown.sh and
  wpa_action.sh.  

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * WPA Supplicant / EAP-AKA (draft-arkko-pppext-eap-aka-12.txt)
3
 
 * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
 
2
 * EAP peer method: EAP-AKA (RFC 4187)
 
3
 * Copyright (c) 2004-2006, Jouni Malinen <jkmaline@cc.hut.fi>
4
4
 *
5
5
 * This program is free software; you can redistribute it and/or modify
6
6
 * it under the terms of the GNU General Public License version 2 as
12
12
 * See README and COPYING for more details.
13
13
 */
14
14
 
15
 
#include <stdlib.h>
16
 
#include <stdio.h>
17
 
#include <string.h>
 
15
#include "includes.h"
18
16
 
19
17
#include "common.h"
20
18
#include "eap_i.h"
21
19
#include "wpa_supplicant.h"
22
 
#include "config_ssid.h"
23
 
#include "sha1.h"
 
20
#include "crypto.h"
24
21
#include "pcsc_funcs.h"
25
22
#include "eap_sim_common.h"
26
23
 
27
 
/* EAP-AKA Subtypes */
28
 
#define EAP_AKA_SUBTYPE_CHALLENGE 1
29
 
#define EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT 2
30
 
#define EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE 4
31
 
#define EAP_AKA_SUBTYPE_IDENTITY 5
32
 
#define EAP_AKA_SUBTYPE_NOTIFICATION 12
33
 
#define EAP_AKA_SUBTYPE_REAUTHENTICATION 13
34
 
#define EAP_AKA_SUBTYPE_CLIENT_ERROR 14
35
 
 
36
 
/* AT_CLIENT_ERROR_CODE error codes */
37
 
#define EAP_AKA_UNABLE_TO_PROCESS_PACKET 0
38
 
 
39
 
#define AKA_AUTS_LEN 14
40
 
#define RES_MAX_LEN 16
41
 
#define IK_LEN 16
42
 
#define CK_LEN 16
43
 
#define EAP_AKA_MAX_FAST_REAUTHS 1000
44
24
 
45
25
struct eap_aka_data {
46
 
        u8 ik[IK_LEN], ck[CK_LEN], res[RES_MAX_LEN];
 
26
        u8 ik[EAP_AKA_IK_LEN], ck[EAP_AKA_CK_LEN], res[EAP_AKA_RES_MAX_LEN];
47
27
        size_t res_len;
48
28
        u8 nonce_s[EAP_SIM_NONCE_S_LEN];
49
29
        u8 mk[EAP_SIM_MK_LEN];
50
30
        u8 k_aut[EAP_SIM_K_AUT_LEN];
51
31
        u8 k_encr[EAP_SIM_K_ENCR_LEN];
52
32
        u8 msk[EAP_SIM_KEYING_DATA_LEN];
53
 
        u8 rand[AKA_RAND_LEN], autn[AKA_AUTN_LEN];
54
 
        u8 auts[AKA_AUTS_LEN];
 
33
        u8 rand[EAP_AKA_RAND_LEN], autn[EAP_AKA_AUTN_LEN];
 
34
        u8 auts[EAP_AKA_AUTS_LEN];
55
35
 
56
36
        int num_id_req, num_notification;
57
37
        u8 *pseudonym;
69
49
static void * eap_aka_init(struct eap_sm *sm)
70
50
{
71
51
        struct eap_aka_data *data;
72
 
        data = malloc(sizeof(*data));
 
52
        data = wpa_zalloc(sizeof(*data));
73
53
        if (data == NULL)
74
54
                return NULL;
75
 
        memset(data, 0, sizeof(*data));
76
55
 
77
56
        data->state = CONTINUE;
78
57
 
102
81
#else /* PCSC_FUNCS */
103
82
        /* These hardcoded Kc and SRES values are used for testing.
104
83
         * Could consider making them configurable. */
105
 
        memset(data->res, '2', RES_MAX_LEN);
106
 
        data->res_len = 16;
107
 
        memset(data->ik, '3', IK_LEN);
108
 
        memset(data->ck, '4', CK_LEN);
 
84
        memset(data->res, '2', EAP_AKA_RES_MAX_LEN);
 
85
        data->res_len = EAP_AKA_RES_MAX_LEN;
 
86
        memset(data->ik, '3', EAP_AKA_IK_LEN);
 
87
        memset(data->ck, '4', EAP_AKA_CK_LEN);
109
88
        {
110
 
                u8 autn[AKA_AUTN_LEN];
111
 
                memset(autn, '1', AKA_AUTN_LEN);
112
 
                if (memcmp(autn, data->autn, AKA_AUTN_LEN) != 0) {
 
89
                u8 autn[EAP_AKA_AUTN_LEN];
 
90
                memset(autn, '1', EAP_AKA_AUTN_LEN);
 
91
                if (memcmp(autn, data->autn, EAP_AKA_AUTN_LEN) != 0) {
113
92
                        wpa_printf(MSG_WARNING, "EAP-AKA: AUTN did not match "
114
93
                                   "with expected value");
115
94
                        return -1;
116
95
                }
117
96
        }
 
97
#if 0
 
98
        {
 
99
                static int test_resync = 1;
 
100
                if (test_resync) {
 
101
                        /* Test Resynchronization */
 
102
                        test_resync = 0;
 
103
                        return -2;
 
104
                }
 
105
        }
 
106
#endif
118
107
        return 0;
119
108
#endif /* PCSC_FUNCS */
120
109
}
121
110
 
122
111
 
123
 
static void eap_aka_derive_mk(struct eap_aka_data *data,
124
 
                              const u8 *identity, size_t identity_len)
125
 
{
126
 
        const u8 *addr[3];
127
 
        size_t len[3];
128
 
 
129
 
        addr[0] = identity;
130
 
        len[0] = identity_len;
131
 
        addr[1] = data->ik;
132
 
        len[1] = IK_LEN;
133
 
        addr[2] = data->ck;
134
 
        len[2] = CK_LEN;
135
 
 
136
 
        /* MK = SHA1(Identity|IK|CK) */
137
 
        sha1_vector(3, addr, len, data->mk);
138
 
        wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: IK", data->ik, IK_LEN);
139
 
        wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: CK", data->ck, CK_LEN);
140
 
        wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: MK", data->mk, EAP_SIM_MK_LEN);
141
 
}
142
 
 
143
 
 
144
112
#define CLEAR_PSEUDONYM 0x01
145
113
#define CLEAR_REAUTH_ID 0x02
146
114
#define CLEAR_EAP_ID    0x04
210
178
}
211
179
 
212
180
 
213
 
static u8 * eap_aka_client_error(struct eap_sm *sm, struct eap_aka_data *data,
214
 
                                 struct eap_hdr *req,
 
181
static u8 * eap_aka_client_error(struct eap_aka_data *data,
 
182
                                 const struct eap_hdr *req,
215
183
                                 size_t *respDataLen, int err)
216
184
{
217
185
        struct eap_sim_msg *msg;
227
195
}
228
196
 
229
197
 
230
 
static u8 * eap_aka_authentication_reject(struct eap_sm *sm,
231
 
                                          struct eap_aka_data *data,
232
 
                                          struct eap_hdr *req,
 
198
static u8 * eap_aka_authentication_reject(struct eap_aka_data *data,
 
199
                                          const struct eap_hdr *req,
233
200
                                          size_t *respDataLen)
234
201
{
235
202
        struct eap_sim_msg *msg;
247
214
}
248
215
 
249
216
 
250
 
static u8 * eap_aka_synchronization_failure(struct eap_sm *sm,
251
 
                                            struct eap_aka_data *data,
252
 
                                            struct eap_hdr *req,
 
217
static u8 * eap_aka_synchronization_failure(struct eap_aka_data *data,
 
218
                                            const struct eap_hdr *req,
253
219
                                            size_t *respDataLen)
254
220
{
255
221
        struct eap_sim_msg *msg;
256
222
 
257
 
        data->state = FAILURE;
258
223
        data->num_id_req = 0;
259
224
        data->num_notification = 0;
260
225
 
264
229
                               EAP_TYPE_AKA,
265
230
                               EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE);
266
231
        wpa_printf(MSG_DEBUG, "   AT_AUTS");
267
 
        eap_sim_msg_add_full(msg, EAP_SIM_AT_AUTS, data->auts, AKA_AUTS_LEN);
 
232
        eap_sim_msg_add_full(msg, EAP_SIM_AT_AUTS, data->auts,
 
233
                             EAP_AKA_AUTS_LEN);
268
234
        return eap_sim_msg_finish(msg, respDataLen, NULL, NULL, 0);
269
235
}
270
236
 
271
237
 
272
238
static u8 * eap_aka_response_identity(struct eap_sm *sm,
273
239
                                      struct eap_aka_data *data,
274
 
                                      struct eap_hdr *req,
 
240
                                      const struct eap_hdr *req,
275
241
                                      size_t *respDataLen,
276
242
                                      enum eap_sim_id_req id_req)
277
243
{
278
 
        struct wpa_ssid *config = eap_get_config(sm);
279
 
        u8 *identity = NULL;
 
244
        const u8 *identity = NULL;
280
245
        size_t identity_len = 0;
281
246
        struct eap_sim_msg *msg;
282
247
 
290
255
                identity = data->pseudonym;
291
256
                identity_len = data->pseudonym_len;
292
257
                eap_aka_clear_identities(data, CLEAR_REAUTH_ID);
293
 
        } else if (id_req != NO_ID_REQ && config && config->identity) {
294
 
                identity = config->identity;
295
 
                identity_len = config->identity_len;
296
 
                eap_aka_clear_identities(data,
297
 
                                         CLEAR_PSEUDONYM | CLEAR_REAUTH_ID);
 
258
        } else if (id_req != NO_ID_REQ) {
 
259
                identity = eap_get_config_identity(sm, &identity_len);
 
260
                if (identity) {
 
261
                        eap_aka_clear_identities(data, CLEAR_PSEUDONYM |
 
262
                                                 CLEAR_REAUTH_ID);
 
263
                }
298
264
        }
299
265
        if (id_req != NO_ID_REQ)
300
266
                eap_aka_clear_identities(data, CLEAR_EAP_ID);
301
267
 
302
268
        wpa_printf(MSG_DEBUG, "Generating EAP-AKA Identity (id=%d)",
303
 
                req->identifier);
 
269
                   req->identifier);
304
270
        msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier,
305
271
                               EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY);
306
272
 
315
281
}
316
282
 
317
283
 
318
 
static u8 * eap_aka_response_challenge(struct eap_sm *sm,
319
 
                                       struct eap_aka_data *data,
320
 
                                       struct eap_hdr *req,
 
284
static u8 * eap_aka_response_challenge(struct eap_aka_data *data,
 
285
                                       const struct eap_hdr *req,
321
286
                                       size_t *respDataLen)
322
287
{
323
288
        struct eap_sim_msg *msg;
324
289
 
325
290
        wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d)",
326
 
                req->identifier);
 
291
                   req->identifier);
327
292
        msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier,
328
293
                               EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE);
329
294
        wpa_printf(MSG_DEBUG, "   AT_RES");
335
300
}
336
301
 
337
302
 
338
 
static u8 * eap_aka_response_reauth(struct eap_sm *sm,
339
 
                                    struct eap_aka_data *data,
340
 
                                    struct eap_hdr *req,
 
303
static u8 * eap_aka_response_reauth(struct eap_aka_data *data,
 
304
                                    const struct eap_hdr *req,
341
305
                                    size_t *respDataLen, int counter_too_small)
342
306
{
343
307
        struct eap_sim_msg *msg;
375
339
}
376
340
 
377
341
 
378
 
static u8 * eap_aka_response_notification(struct eap_sm *sm,
379
 
                                          struct eap_aka_data *data,
380
 
                                          struct eap_hdr *req,
 
342
static u8 * eap_aka_response_notification(struct eap_aka_data *data,
 
343
                                          const struct eap_hdr *req,
381
344
                                          size_t *respDataLen,
382
345
                                          u16 notification)
383
346
{
416
379
 
417
380
static u8 * eap_aka_process_identity(struct eap_sm *sm,
418
381
                                     struct eap_aka_data *data,
419
 
                                     struct eap_hdr *req, size_t reqDataLen,
 
382
                                     const struct eap_hdr *req,
420
383
                                     size_t *respDataLen,
421
384
                                     struct eap_sim_attrs *attr)
422
385
{
447
410
        if (id_error) {
448
411
                wpa_printf(MSG_INFO, "EAP-AKA: Too many ID requests "
449
412
                           "used within one authentication");
450
 
                return eap_aka_client_error(sm, data, req, respDataLen,
 
413
                return eap_aka_client_error(data, req, respDataLen,
451
414
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
452
415
        }
453
416
 
458
421
 
459
422
static u8 * eap_aka_process_challenge(struct eap_sm *sm,
460
423
                                      struct eap_aka_data *data,
461
 
                                      struct eap_hdr *req, size_t reqDataLen,
 
424
                                      const struct eap_hdr *req,
 
425
                                      size_t reqDataLen,
462
426
                                      size_t *respDataLen,
463
427
                                      struct eap_sim_attrs *attr)
464
428
{
465
 
        struct wpa_ssid *config = eap_get_config(sm);
466
 
        u8 *identity;
 
429
        const u8 *identity;
467
430
        size_t identity_len;
468
431
        int res;
469
432
        struct eap_sim_attrs eattr;
476
439
                           !attr->mac ? " AT_MAC" : "",
477
440
                           !attr->rand ? " AT_RAND" : "",
478
441
                           !attr->autn ? " AT_AUTN" : "");
479
 
                return eap_aka_client_error(sm, data, req, respDataLen,
 
442
                return eap_aka_client_error(data, req, respDataLen,
480
443
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
481
444
        }
482
 
        memcpy(data->rand, attr->rand, AKA_RAND_LEN);
483
 
        memcpy(data->autn, attr->autn, AKA_AUTN_LEN);
 
445
        memcpy(data->rand, attr->rand, EAP_AKA_RAND_LEN);
 
446
        memcpy(data->autn, attr->autn, EAP_AKA_AUTN_LEN);
484
447
 
485
448
        res = eap_aka_umts_auth(sm, data);
486
449
        if (res == -1) {
487
450
                wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication "
488
451
                           "failed (AUTN)");
489
 
                return eap_aka_authentication_reject(sm, data, req,
490
 
                                                     respDataLen);
 
452
                return eap_aka_authentication_reject(data, req, respDataLen);
491
453
        } else if (res == -2) {
492
454
                wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication "
493
455
                           "failed (AUTN seq# -> AUTS)");
494
 
                return eap_aka_synchronization_failure(sm, data, req,
495
 
                                                       respDataLen);
 
456
                return eap_aka_synchronization_failure(data, req, respDataLen);
496
457
        } else if (res) {
497
458
                wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication failed");
498
 
                return eap_aka_client_error(sm, data, req, respDataLen,
 
459
                return eap_aka_client_error(data, req, respDataLen,
499
460
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
500
461
        }
501
462
        if (data->last_eap_identity) {
504
465
        } else if (data->pseudonym) {
505
466
                identity = data->pseudonym;
506
467
                identity_len = data->pseudonym_len;
507
 
        } else {
508
 
                identity = config->identity;
509
 
                identity_len = config->identity_len;
510
 
        }
 
468
        } else
 
469
                identity = eap_get_config_identity(sm, &identity_len);
511
470
        wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Selected identity for MK "
512
471
                          "derivation", identity, identity_len);
513
 
        eap_aka_derive_mk(data, identity, identity_len);
 
472
        eap_aka_derive_mk(identity, identity_len, data->ik, data->ck,
 
473
                          data->mk);
514
474
        eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk);
515
 
        if (eap_sim_verify_mac(data->k_aut, (u8 *) req, reqDataLen, attr->mac,
516
 
                               (u8 *) "", 0)) {
 
475
        if (eap_sim_verify_mac(data->k_aut, (const u8 *) req, reqDataLen,
 
476
                               attr->mac, (u8 *) "", 0)) {
517
477
                wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
518
478
                           "used invalid AT_MAC");
519
 
                return eap_aka_client_error(sm, data, req, respDataLen,
 
479
                return eap_aka_client_error(data, req, respDataLen,
520
480
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
521
481
        }
522
482
 
527
487
                                 CLEAR_EAP_ID);
528
488
 
529
489
        if (attr->encr_data) {
530
 
                if (eap_sim_parse_encr(data->k_encr, attr->encr_data,
531
 
                                       attr->encr_data_len, attr->iv, &eattr,
532
 
                                       0)) {
 
490
                u8 *decrypted;
 
491
                decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
 
492
                                               attr->encr_data_len, attr->iv,
 
493
                                               &eattr, 0);
 
494
                if (decrypted == NULL) {
533
495
                        return eap_aka_client_error(
534
 
                                sm, data, req, respDataLen,
 
496
                                data, req, respDataLen,
535
497
                                EAP_AKA_UNABLE_TO_PROCESS_PACKET);
536
498
                }
537
499
                eap_aka_learn_ids(data, &eattr);
 
500
                free(decrypted);
538
501
        }
539
502
 
540
503
        if (data->state != FAILURE)
542
505
 
543
506
        data->num_id_req = 0;
544
507
        data->num_notification = 0;
545
 
        /* draft-arkko-pppext-eap-aka-12.txt specifies that counter
546
 
         * is initialized to one after fullauth, but initializing it to
547
 
         * zero makes it easier to implement reauth verification. */
 
508
        /* RFC 4187 specifies that counter is initialized to one after
 
509
         * fullauth, but initializing it to zero makes it easier to implement
 
510
         * reauth verification. */
548
511
        data->counter = 0;
549
 
        return eap_aka_response_challenge(sm, data, req, respDataLen);
 
512
        return eap_aka_response_challenge(data, req, respDataLen);
550
513
}
551
514
 
552
515
 
553
516
static int eap_aka_process_notification_reauth(struct eap_aka_data *data,
554
 
                                               struct eap_hdr *req,
555
 
                                               size_t reqDataLen,
556
517
                                               struct eap_sim_attrs *attr)
557
518
{
558
519
        struct eap_sim_attrs eattr;
 
520
        u8 *decrypted;
559
521
 
560
522
        if (attr->encr_data == NULL || attr->iv == NULL) {
561
523
                wpa_printf(MSG_WARNING, "EAP-AKA: Notification message after "
563
525
                return -1;
564
526
        }
565
527
 
566
 
        if (eap_sim_parse_encr(data->k_encr, attr->encr_data,
567
 
                               attr->encr_data_len, attr->iv, &eattr, 0)) {
 
528
        decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
 
529
                                       attr->encr_data_len, attr->iv, &eattr,
 
530
                                       0);
 
531
        if (decrypted == NULL) {
568
532
                wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
569
533
                           "data from notification message");
570
534
                return -1;
571
535
        }
572
536
 
573
 
        if (eattr.counter != data->counter) {
 
537
        if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) {
574
538
                wpa_printf(MSG_WARNING, "EAP-AKA: Counter in notification "
575
539
                           "message does not match with counter in reauth "
576
540
                           "message");
 
541
                free(decrypted);
577
542
                return -1;
578
543
        }
579
544
 
 
545
        free(decrypted);
580
546
        return 0;
581
547
}
582
548
 
583
549
 
584
550
static int eap_aka_process_notification_auth(struct eap_aka_data *data,
585
 
                                             struct eap_hdr *req,
 
551
                                             const struct eap_hdr *req,
586
552
                                             size_t reqDataLen,
587
553
                                             struct eap_sim_attrs *attr)
588
554
{
592
558
                return -1;
593
559
        }
594
560
 
595
 
        if (eap_sim_verify_mac(data->k_aut, (u8 *) req, reqDataLen, attr->mac,
596
 
                               (u8 *) "", 0)) {
 
561
        if (eap_sim_verify_mac(data->k_aut, (const u8 *) req, reqDataLen,
 
562
                               attr->mac, (u8 *) "", 0)) {
597
563
                wpa_printf(MSG_WARNING, "EAP-AKA: Notification message "
598
564
                           "used invalid AT_MAC");
599
565
                return -1;
600
566
        }
601
567
 
602
568
        if (data->reauth &&
603
 
            eap_aka_process_notification_reauth(data, req, reqDataLen, attr)) {
 
569
            eap_aka_process_notification_reauth(data, attr)) {
604
570
                wpa_printf(MSG_WARNING, "EAP-AKA: Invalid notification "
605
571
                           "message after reauth");
606
572
                return -1;
612
578
 
613
579
static u8 * eap_aka_process_notification(struct eap_sm *sm,
614
580
                                         struct eap_aka_data *data,
615
 
                                         struct eap_hdr *req,
 
581
                                         const struct eap_hdr *req,
616
582
                                         size_t reqDataLen,
617
583
                                         size_t *respDataLen,
618
584
                                         struct eap_sim_attrs *attr)
621
587
        if (data->num_notification > 0) {
622
588
                wpa_printf(MSG_INFO, "EAP-AKA: too many notification "
623
589
                           "rounds (only one allowed)");
624
 
                return eap_aka_client_error(sm, data, req, respDataLen,
 
590
                return eap_aka_client_error(data, req, respDataLen,
625
591
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
626
592
        }
627
593
        data->num_notification++;
628
594
        if (attr->notification == -1) {
629
595
                wpa_printf(MSG_INFO, "EAP-AKA: no AT_NOTIFICATION in "
630
596
                           "Notification message");
631
 
                return eap_aka_client_error(sm, data, req, respDataLen,
 
597
                return eap_aka_client_error(data, req, respDataLen,
632
598
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
633
599
        }
634
600
 
635
601
        if ((attr->notification & 0x4000) == 0 &&
636
602
            eap_aka_process_notification_auth(data, req, reqDataLen, attr)) {
637
 
                return eap_aka_client_error(sm, data, req, respDataLen,
 
603
                return eap_aka_client_error(data, req, respDataLen,
638
604
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
639
605
        }
640
606
 
642
608
        if (attr->notification >= 0 && attr->notification < 32768) {
643
609
                data->state = FAILURE;
644
610
        }
645
 
        return eap_aka_response_notification(sm, data, req, respDataLen,
 
611
        return eap_aka_response_notification(data, req, respDataLen,
646
612
                                             attr->notification);
647
613
}
648
614
 
649
615
 
650
616
static u8 * eap_aka_process_reauthentication(struct eap_sm *sm,
651
617
                                             struct eap_aka_data *data,
652
 
                                             struct eap_hdr *req,
 
618
                                             const struct eap_hdr *req,
653
619
                                             size_t reqDataLen,
654
620
                                             size_t *respDataLen,
655
621
                                             struct eap_sim_attrs *attr)
656
622
{
657
623
        struct eap_sim_attrs eattr;
 
624
        u8 *decrypted;
658
625
 
659
626
        wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Reauthentication");
660
627
 
661
628
        if (data->reauth_id == NULL) {
662
629
                wpa_printf(MSG_WARNING, "EAP-AKA: Server is trying "
663
630
                           "reauthentication, but no reauth_id available");
664
 
                return eap_aka_client_error(sm, data, req, respDataLen,
 
631
                return eap_aka_client_error(data, req, respDataLen,
665
632
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
666
633
        }
667
634
 
668
635
        data->reauth = 1;
669
 
        if (eap_sim_verify_mac(data->k_aut, (u8 *) req, reqDataLen,
 
636
        if (eap_sim_verify_mac(data->k_aut, (const u8 *) req, reqDataLen,
670
637
                               attr->mac, (u8 *) "", 0)) {
671
638
                wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
672
639
                           "did not have valid AT_MAC");
673
 
                return eap_aka_client_error(sm, data, req, respDataLen,
 
640
                return eap_aka_client_error(data, req, respDataLen,
674
641
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
675
642
        }
676
643
 
677
644
        if (attr->encr_data == NULL || attr->iv == NULL) {
678
645
                wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
679
646
                           "message did not include encrypted data");
680
 
                return eap_aka_client_error(sm, data, req, respDataLen,
 
647
                return eap_aka_client_error(data, req, respDataLen,
681
648
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
682
649
        }
683
650
 
684
 
        if (eap_sim_parse_encr(data->k_encr, attr->encr_data,
685
 
                               attr->encr_data_len, attr->iv, &eattr, 0)) {
 
651
        decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
 
652
                                       attr->encr_data_len, attr->iv, &eattr,
 
653
                                       0);
 
654
        if (decrypted == NULL) {
686
655
                wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
687
656
                           "data from reauthentication message");
688
 
                return eap_aka_client_error(sm, data, req, respDataLen,
 
657
                return eap_aka_client_error(data, req, respDataLen,
689
658
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
690
659
        }
691
660
 
693
662
                wpa_printf(MSG_INFO, "EAP-AKA: (encr) No%s%s in reauth packet",
694
663
                           !eattr.nonce_s ? " AT_NONCE_S" : "",
695
664
                           eattr.counter < 0 ? " AT_COUNTER" : "");
696
 
                return eap_aka_client_error(sm, data, req, respDataLen,
 
665
                free(decrypted);
 
666
                return eap_aka_client_error(data, req, respDataLen,
697
667
                                            EAP_AKA_UNABLE_TO_PROCESS_PACKET);
698
668
        }
699
669
 
700
 
        if (eattr.counter <= data->counter) {
 
670
        if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) {
701
671
                wpa_printf(MSG_INFO, "EAP-AKA: (encr) Invalid counter "
702
672
                           "(%d <= %d)", eattr.counter, data->counter);
703
673
                data->counter_too_small = eattr.counter;
711
681
                data->last_eap_identity_len = data->reauth_id_len;
712
682
                data->reauth_id = NULL;
713
683
                data->reauth_id_len = 0;
714
 
                return eap_aka_response_reauth(sm, data, req, respDataLen, 1);
 
684
                free(decrypted);
 
685
                return eap_aka_response_reauth(data, req, respDataLen, 1);
715
686
        }
716
687
        data->counter = eattr.counter;
717
688
 
735
706
                           "fast reauths performed - force fullauth");
736
707
                eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
737
708
        }
738
 
        return eap_aka_response_reauth(sm, data, req, respDataLen, 0);
 
709
        free(decrypted);
 
710
        return eap_aka_response_reauth(data, req, respDataLen, 0);
739
711
}
740
712
 
741
713
 
742
714
static u8 * eap_aka_process(struct eap_sm *sm, void *priv,
743
715
                            struct eap_method_ret *ret,
744
 
                            u8 *reqData, size_t reqDataLen,
 
716
                            const u8 *reqData, size_t reqDataLen,
745
717
                            size_t *respDataLen)
746
718
{
747
719
        struct eap_aka_data *data = priv;
748
 
        struct wpa_ssid *config = eap_get_config(sm);
749
 
        struct eap_hdr *req;
750
 
        u8 *pos, subtype, *res;
 
720
        const struct eap_hdr *req;
 
721
        u8 subtype, *res;
 
722
        const u8 *pos;
751
723
        struct eap_sim_attrs attr;
752
724
        size_t len;
753
725
 
754
726
        wpa_hexdump(MSG_DEBUG, "EAP-AKA: EAP data", reqData, reqDataLen);
755
 
        if (config == NULL || config->identity == NULL) {
 
727
        if (eap_get_config_identity(sm, &len) == NULL) {
756
728
                wpa_printf(MSG_INFO, "EAP-AKA: Identity not configured");
757
 
                eap_sm_request_identity(sm, config);
 
729
                eap_sm_request_identity(sm);
758
730
                ret->ignore = TRUE;
759
731
                return NULL;
760
732
        }
761
733
 
762
 
        req = (struct eap_hdr *) reqData;
763
 
        pos = (u8 *) (req + 1);
764
 
        if (reqDataLen < sizeof(*req) + 4 || *pos != EAP_TYPE_AKA ||
765
 
            (len = be_to_host16(req->length)) > reqDataLen) {
766
 
                wpa_printf(MSG_INFO, "EAP-AKA: Invalid frame");
 
734
        pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_AKA,
 
735
                               reqData, reqDataLen, &len);
 
736
        if (pos == NULL || len < 1) {
767
737
                ret->ignore = TRUE;
768
738
                return NULL;
769
739
        }
 
740
        req = (const struct eap_hdr *) reqData;
 
741
        len = be_to_host16(req->length);
770
742
 
771
743
        ret->ignore = FALSE;
772
 
        ret->methodState = METHOD_CONT;
 
744
        ret->methodState = METHOD_MAY_CONT;
773
745
        ret->decision = DECISION_FAIL;
774
746
        ret->allowNotifications = TRUE;
775
747
 
776
 
        pos++;
777
748
        subtype = *pos++;
778
749
        wpa_printf(MSG_DEBUG, "EAP-AKA: Subtype=%d", subtype);
779
750
        pos += 2; /* Reserved */
780
751
 
781
752
        if (eap_sim_parse_attr(pos, reqData + len, &attr, 1, 0)) {
782
 
                res = eap_aka_client_error(sm, data, req, respDataLen,
 
753
                res = eap_aka_client_error(data, req, respDataLen,
783
754
                                           EAP_AKA_UNABLE_TO_PROCESS_PACKET);
784
755
                goto done;
785
756
        }
786
757
 
787
758
        switch (subtype) {
788
759
        case EAP_AKA_SUBTYPE_IDENTITY:
789
 
                res = eap_aka_process_identity(sm, data, req, len,
 
760
                res = eap_aka_process_identity(sm, data, req,
790
761
                                               respDataLen, &attr);
791
762
                break;
792
763
        case EAP_AKA_SUBTYPE_CHALLENGE:
803
774
                break;
804
775
        case EAP_AKA_SUBTYPE_CLIENT_ERROR:
805
776
                wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Client-Error");
806
 
                res = eap_aka_client_error(sm, data, req, respDataLen,
 
777
                res = eap_aka_client_error(data, req, respDataLen,
807
778
                                           EAP_AKA_UNABLE_TO_PROCESS_PACKET);
808
779
                break;
809
780
        default:
810
781
                wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown subtype=%d", subtype);
811
 
                res = eap_aka_client_error(sm, data, req, respDataLen,
 
782
                res = eap_aka_client_error(data, req, respDataLen,
812
783
                                           EAP_AKA_UNABLE_TO_PROCESS_PACKET);
813
784
                break;
814
785
        }
818
789
                ret->decision = DECISION_FAIL;
819
790
                ret->methodState = METHOD_DONE;
820
791
        } else if (data->state == SUCCESS) {
821
 
                ret->decision = DECISION_UNCOND_SUCC;
 
792
                ret->decision = DECISION_COND_SUCC;
822
793
                ret->methodState = METHOD_DONE;
823
794
        }
824
795
 
899
870
}
900
871
 
901
872
 
902
 
const struct eap_method eap_method_aka =
 
873
int eap_peer_aka_register(void)
903
874
{
904
 
        .method = EAP_TYPE_AKA,
905
 
        .name = "AKA",
906
 
        .init = eap_aka_init,
907
 
        .deinit = eap_aka_deinit,
908
 
        .process = eap_aka_process,
909
 
        .isKeyAvailable = eap_aka_isKeyAvailable,
910
 
        .getKey = eap_aka_getKey,
911
 
        .has_reauth_data = eap_aka_has_reauth_data,
912
 
        .deinit_for_reauth = eap_aka_deinit_for_reauth,
913
 
        .init_for_reauth = eap_aka_init_for_reauth,
914
 
        .get_identity = eap_aka_get_identity,
915
 
};
 
875
        struct eap_method *eap;
 
876
        int ret;
 
877
 
 
878
        eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
 
879
                                    EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA");
 
880
        if (eap == NULL)
 
881
                return -1;
 
882
 
 
883
        eap->init = eap_aka_init;
 
884
        eap->deinit = eap_aka_deinit;
 
885
        eap->process = eap_aka_process;
 
886
        eap->isKeyAvailable = eap_aka_isKeyAvailable;
 
887
        eap->getKey = eap_aka_getKey;
 
888
        eap->has_reauth_data = eap_aka_has_reauth_data;
 
889
        eap->deinit_for_reauth = eap_aka_deinit_for_reauth;
 
890
        eap->init_for_reauth = eap_aka_init_for_reauth;
 
891
        eap->get_identity = eap_aka_get_identity;
 
892
 
 
893
        ret = eap_peer_method_register(eap);
 
894
        if (ret)
 
895
                eap_peer_method_free(eap);
 
896
        return ret;
 
897
}