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

« back to all changes in this revision

Viewing changes to src/eap_peer/eap_pax.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-PAX (RFC 4746)
 
3
 * Copyright (c) 2005-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_common/eap_pax_common.h"
 
20
#include "sha1.h"
 
21
#include "crypto.h"
 
22
 
 
23
/*
 
24
 * Note: only PAX_STD subprotocol is currently supported
 
25
 *
 
26
 * TODO: Add support with PAX_SEC with the mandatory to implement ciphersuite
 
27
 * (HMAC_SHA1_128, IANA DH Group 14 (2048 bits), RSA-PKCS1-V1_5) and
 
28
 * recommended ciphersuite (HMAC_SHA256_128, IANA DH Group 15 (3072 bits),
 
29
 * RSAES-OAEP).
 
30
 */
 
31
 
 
32
struct eap_pax_data {
 
33
        enum { PAX_INIT, PAX_STD_2_SENT, PAX_DONE } state;
 
34
        u8 mac_id, dh_group_id, public_key_id;
 
35
        union {
 
36
                u8 e[2 * EAP_PAX_RAND_LEN];
 
37
                struct {
 
38
                        u8 x[EAP_PAX_RAND_LEN]; /* server rand */
 
39
                        u8 y[EAP_PAX_RAND_LEN]; /* client rand */
 
40
                } r;
 
41
        } rand;
 
42
        char *cid;
 
43
        size_t cid_len;
 
44
        u8 ak[EAP_PAX_AK_LEN];
 
45
        u8 mk[EAP_PAX_MK_LEN];
 
46
        u8 ck[EAP_PAX_CK_LEN];
 
47
        u8 ick[EAP_PAX_ICK_LEN];
 
48
};
 
49
 
 
50
 
 
51
static void eap_pax_deinit(struct eap_sm *sm, void *priv);
 
52
 
 
53
 
 
54
static void * eap_pax_init(struct eap_sm *sm)
 
55
{
 
56
        struct eap_pax_data *data;
 
57
        const u8 *identity, *password;
 
58
        size_t identity_len, password_len;
 
59
 
 
60
        identity = eap_get_config_identity(sm, &identity_len);
 
61
        password = eap_get_config_password(sm, &password_len);
 
62
        if (!identity || !password) {
 
63
                wpa_printf(MSG_INFO, "EAP-PAX: CID (nai) or key (password) "
 
64
                           "not configured");
 
65
                return NULL;
 
66
        }
 
67
 
 
68
        if (password_len != EAP_PAX_AK_LEN) {
 
69
                wpa_printf(MSG_INFO, "EAP-PAX: Invalid PSK length");
 
70
                return NULL;
 
71
        }
 
72
 
 
73
        data = os_zalloc(sizeof(*data));
 
74
        if (data == NULL)
 
75
                return NULL;
 
76
        data->state = PAX_INIT;
 
77
 
 
78
        data->cid = os_malloc(identity_len);
 
79
        if (data->cid == NULL) {
 
80
                eap_pax_deinit(sm, data);
 
81
                return NULL;
 
82
        }
 
83
        os_memcpy(data->cid, identity, identity_len);
 
84
        data->cid_len = identity_len;
 
85
 
 
86
        os_memcpy(data->ak, password, EAP_PAX_AK_LEN);
 
87
 
 
88
        return data;
 
89
}
 
90
 
 
91
 
 
92
static void eap_pax_deinit(struct eap_sm *sm, void *priv)
 
93
{
 
94
        struct eap_pax_data *data = priv;
 
95
        os_free(data->cid);
 
96
        os_free(data);
 
97
}
 
98
 
 
99
 
 
100
static struct wpabuf * eap_pax_alloc_resp(const struct eap_pax_hdr *req,
 
101
                                          u8 id, u8 op_code, size_t plen)
 
102
{
 
103
        struct wpabuf *resp;
 
104
        struct eap_pax_hdr *pax;
 
105
 
 
106
        resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PAX,
 
107
                             sizeof(*pax) + plen, EAP_CODE_RESPONSE, id);
 
108
        if (resp == NULL)
 
109
                return NULL;
 
110
 
 
111
        pax = wpabuf_put(resp, sizeof(*pax));
 
112
        pax->op_code = op_code;
 
113
        pax->flags = 0;
 
114
        pax->mac_id = req->mac_id;
 
115
        pax->dh_group_id = req->dh_group_id;
 
116
        pax->public_key_id = req->public_key_id;
 
117
 
 
118
        return resp;
 
119
}
 
120
 
 
121
 
 
122
static struct wpabuf * eap_pax_process_std_1(struct eap_pax_data *data,
 
123
                                             struct eap_method_ret *ret, u8 id,
 
124
                                             const struct eap_pax_hdr *req,
 
125
                                             size_t req_plen)
 
126
{
 
127
        struct wpabuf *resp;
 
128
        const u8 *pos;
 
129
        u8 *rpos;
 
130
        size_t left, plen;
 
131
 
 
132
        wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-1 (received)");
 
133
 
 
134
        if (data->state != PAX_INIT) {
 
135
                wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 received in "
 
136
                           "unexpected state (%d) - ignored", data->state);
 
137
                ret->ignore = TRUE;
 
138
                return NULL;
 
139
        }
 
140
 
 
141
        if (req->flags & EAP_PAX_FLAGS_CE) {
 
142
                wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with CE flag set - "
 
143
                           "ignored");
 
144
                ret->ignore = TRUE;
 
145
                return NULL;
 
146
        }
 
147
 
 
148
        left = req_plen - sizeof(*req);
 
149
 
 
150
        if (left < 2 + EAP_PAX_RAND_LEN) {
 
151
                wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with too short "
 
152
                           "payload");
 
153
                ret->ignore = TRUE;
 
154
                return NULL;
 
155
        }
 
156
 
 
157
        pos = (const u8 *) (req + 1);
 
158
        if (WPA_GET_BE16(pos) != EAP_PAX_RAND_LEN) {
 
159
                wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with incorrect A "
 
160
                           "length %d (expected %d)",
 
161
                           WPA_GET_BE16(pos), EAP_PAX_RAND_LEN);
 
162
                ret->ignore = TRUE;
 
163
                return NULL;
 
164
        }
 
165
 
 
166
        pos += 2;
 
167
        left -= 2;
 
168
        os_memcpy(data->rand.r.x, pos, EAP_PAX_RAND_LEN);
 
169
        wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: X (server rand)",
 
170
                    data->rand.r.x, EAP_PAX_RAND_LEN);
 
171
        pos += EAP_PAX_RAND_LEN;
 
172
        left -= EAP_PAX_RAND_LEN;
 
173
 
 
174
        if (left > 0) {
 
175
                wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ignored extra payload",
 
176
                            pos, left);
 
177
        }
 
178
 
 
179
        if (os_get_random(data->rand.r.y, EAP_PAX_RAND_LEN)) {
 
180
                wpa_printf(MSG_ERROR, "EAP-PAX: Failed to get random data");
 
181
                ret->ignore = TRUE;
 
182
                return NULL;
 
183
        }
 
184
        wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Y (client rand)",
 
185
                    data->rand.r.y, EAP_PAX_RAND_LEN);
 
186
 
 
187
        if (eap_pax_initial_key_derivation(req->mac_id, data->ak, data->rand.e,
 
188
                                           data->mk, data->ck, data->ick) < 0)
 
189
        {
 
190
                ret->ignore = TRUE;
 
191
                return NULL;
 
192
        }
 
193
 
 
194
        wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-2 (sending)");
 
195
 
 
196
        plen = 2 + EAP_PAX_RAND_LEN + 2 + data->cid_len + 2 + EAP_PAX_MAC_LEN +
 
197
                EAP_PAX_ICV_LEN;
 
198
        resp = eap_pax_alloc_resp(req, id, EAP_PAX_OP_STD_2, plen);
 
199
        if (resp == NULL)
 
200
                return NULL;
 
201
 
 
202
        wpabuf_put_be16(resp, EAP_PAX_RAND_LEN);
 
203
        wpabuf_put_data(resp, data->rand.r.y, EAP_PAX_RAND_LEN);
 
204
        wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: B = Y (client rand)",
 
205
                    data->rand.r.y, EAP_PAX_RAND_LEN);
 
206
 
 
207
        wpabuf_put_be16(resp, data->cid_len);
 
208
        wpabuf_put_data(resp, data->cid, data->cid_len);
 
209
        wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-PAX: CID",
 
210
                          (u8 *) data->cid, data->cid_len);
 
211
 
 
212
        wpabuf_put_be16(resp, EAP_PAX_MAC_LEN);
 
213
        rpos = wpabuf_put(resp, EAP_PAX_MAC_LEN);
 
214
        eap_pax_mac(req->mac_id, data->ck, EAP_PAX_CK_LEN,
 
215
                    data->rand.r.x, EAP_PAX_RAND_LEN,
 
216
                    data->rand.r.y, EAP_PAX_RAND_LEN,
 
217
                    (u8 *) data->cid, data->cid_len, rpos);
 
218
        wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(A, B, CID)",
 
219
                    rpos, EAP_PAX_MAC_LEN);
 
220
 
 
221
        /* Optional ADE could be added here, if needed */
 
222
 
 
223
        rpos = wpabuf_put(resp, EAP_PAX_ICV_LEN);
 
224
        eap_pax_mac(req->mac_id, data->ick, EAP_PAX_ICK_LEN,
 
225
                    wpabuf_head(resp), wpabuf_len(resp) - EAP_PAX_ICV_LEN,
 
226
                    NULL, 0, NULL, 0, rpos);
 
227
        wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", rpos, EAP_PAX_ICV_LEN);
 
228
 
 
229
        data->state = PAX_STD_2_SENT;
 
230
        data->mac_id = req->mac_id;
 
231
        data->dh_group_id = req->dh_group_id;
 
232
        data->public_key_id = req->public_key_id;
 
233
 
 
234
        return resp;
 
235
}
 
236
 
 
237
 
 
238
static struct wpabuf * eap_pax_process_std_3(struct eap_pax_data *data,
 
239
                                             struct eap_method_ret *ret, u8 id,
 
240
                                             const struct eap_pax_hdr *req,
 
241
                                             size_t req_plen)
 
242
{
 
243
        struct wpabuf *resp;
 
244
        u8 *rpos, mac[EAP_PAX_MAC_LEN];
 
245
        const u8 *pos;
 
246
        size_t left;
 
247
 
 
248
        wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-3 (received)");
 
249
 
 
250
        if (data->state != PAX_STD_2_SENT) {
 
251
                wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 received in "
 
252
                           "unexpected state (%d) - ignored", data->state);
 
253
                ret->ignore = TRUE;
 
254
                return NULL;
 
255
        }
 
256
 
 
257
        if (req->flags & EAP_PAX_FLAGS_CE) {
 
258
                wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 with CE flag set - "
 
259
                           "ignored");
 
260
                ret->ignore = TRUE;
 
261
                return NULL;
 
262
        }
 
263
 
 
264
        left = req_plen - sizeof(*req);
 
265
 
 
266
        if (left < 2 + EAP_PAX_MAC_LEN) {
 
267
                wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 with too short "
 
268
                           "payload");
 
269
                ret->ignore = TRUE;
 
270
                return NULL;
 
271
        }
 
272
 
 
273
        pos = (const u8 *) (req + 1);
 
274
        if (WPA_GET_BE16(pos) != EAP_PAX_MAC_LEN) {
 
275
                wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 with incorrect "
 
276
                           "MAC_CK length %d (expected %d)",
 
277
                           WPA_GET_BE16(pos), EAP_PAX_MAC_LEN);
 
278
                ret->ignore = TRUE;
 
279
                return NULL;
 
280
        }
 
281
        pos += 2;
 
282
        left -= 2;
 
283
        wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(B, CID)",
 
284
                    pos, EAP_PAX_MAC_LEN);
 
285
        eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN,
 
286
                    data->rand.r.y, EAP_PAX_RAND_LEN,
 
287
                    (u8 *) data->cid, data->cid_len, NULL, 0, mac);
 
288
        if (os_memcmp(pos, mac, EAP_PAX_MAC_LEN) != 0) {
 
289
                wpa_printf(MSG_INFO, "EAP-PAX: Invalid MAC_CK(B, CID) "
 
290
                           "received");
 
291
                wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: expected MAC_CK(B, CID)",
 
292
                            mac, EAP_PAX_MAC_LEN);
 
293
                ret->methodState = METHOD_DONE;
 
294
                ret->decision = DECISION_FAIL;
 
295
                return NULL;
 
296
        }
 
297
 
 
298
        pos += EAP_PAX_MAC_LEN;
 
299
        left -= EAP_PAX_MAC_LEN;
 
300
 
 
301
        if (left > 0) {
 
302
                wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ignored extra payload",
 
303
                            pos, left);
 
304
        }
 
305
 
 
306
        wpa_printf(MSG_DEBUG, "EAP-PAX: PAX-ACK (sending)");
 
307
 
 
308
        resp = eap_pax_alloc_resp(req, id, EAP_PAX_OP_ACK, EAP_PAX_ICV_LEN);
 
309
        if (resp == NULL)
 
310
                return NULL;
 
311
 
 
312
        /* Optional ADE could be added here, if needed */
 
313
 
 
314
        rpos = wpabuf_put(resp, EAP_PAX_ICV_LEN);
 
315
        eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN,
 
316
                    wpabuf_head(resp), wpabuf_len(resp) - EAP_PAX_ICV_LEN,
 
317
                    NULL, 0, NULL, 0, rpos);
 
318
        wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", rpos, EAP_PAX_ICV_LEN);
 
319
 
 
320
        data->state = PAX_DONE;
 
321
        ret->methodState = METHOD_DONE;
 
322
        ret->decision = DECISION_UNCOND_SUCC;
 
323
        ret->allowNotifications = FALSE;
 
324
 
 
325
        return resp;
 
326
}
 
327
 
 
328
 
 
329
static struct wpabuf * eap_pax_process(struct eap_sm *sm, void *priv,
 
330
                                       struct eap_method_ret *ret,
 
331
                                       const struct wpabuf *reqData)
 
332
{
 
333
        struct eap_pax_data *data = priv;
 
334
        const struct eap_pax_hdr *req;
 
335
        struct wpabuf *resp;
 
336
        u8 icvbuf[EAP_PAX_ICV_LEN], id;
 
337
        const u8 *icv, *pos;
 
338
        size_t len;
 
339
        u16 flen, mlen;
 
340
 
 
341
        pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, reqData, &len);
 
342
        if (pos == NULL || len < EAP_PAX_ICV_LEN) {
 
343
                ret->ignore = TRUE;
 
344
                return NULL;
 
345
        }
 
346
        id = eap_get_id(reqData);
 
347
        req = (const struct eap_pax_hdr *) pos;
 
348
        flen = len - EAP_PAX_ICV_LEN;
 
349
        mlen = wpabuf_len(reqData) - EAP_PAX_ICV_LEN;
 
350
 
 
351
        wpa_printf(MSG_DEBUG, "EAP-PAX: received frame: op_code 0x%x "
 
352
                   "flags 0x%x mac_id 0x%x dh_group_id 0x%x "
 
353
                   "public_key_id 0x%x",
 
354
                   req->op_code, req->flags, req->mac_id, req->dh_group_id,
 
355
                   req->public_key_id);
 
356
        wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: received payload",
 
357
                    pos, len - EAP_PAX_ICV_LEN);
 
358
 
 
359
        if (data->state != PAX_INIT && data->mac_id != req->mac_id) {
 
360
                wpa_printf(MSG_INFO, "EAP-PAX: MAC ID changed during "
 
361
                           "authentication (was 0x%d, is 0x%d)",
 
362
                           data->mac_id, req->mac_id);
 
363
                ret->ignore = TRUE;
 
364
                return NULL;
 
365
        }
 
366
 
 
367
        if (data->state != PAX_INIT && data->dh_group_id != req->dh_group_id) {
 
368
                wpa_printf(MSG_INFO, "EAP-PAX: DH Group ID changed during "
 
369
                           "authentication (was 0x%d, is 0x%d)",
 
370
                           data->dh_group_id, req->dh_group_id);
 
371
                ret->ignore = TRUE;
 
372
                return NULL;
 
373
        }
 
374
 
 
375
        if (data->state != PAX_INIT &&
 
376
            data->public_key_id != req->public_key_id) {
 
377
                wpa_printf(MSG_INFO, "EAP-PAX: Public Key ID changed during "
 
378
                           "authentication (was 0x%d, is 0x%d)",
 
379
                           data->public_key_id, req->public_key_id);
 
380
                ret->ignore = TRUE;
 
381
                return NULL;
 
382
        }
 
383
 
 
384
        /* TODO: add support EAP_PAX_HMAC_SHA256_128 */
 
385
        if (req->mac_id != EAP_PAX_MAC_HMAC_SHA1_128) {
 
386
                wpa_printf(MSG_INFO, "EAP-PAX: Unsupported MAC ID 0x%x",
 
387
                           req->mac_id);
 
388
                ret->ignore = TRUE;
 
389
                return NULL;
 
390
        }
 
391
 
 
392
        if (req->dh_group_id != EAP_PAX_DH_GROUP_NONE) {
 
393
                wpa_printf(MSG_INFO, "EAP-PAX: Unsupported DH Group ID 0x%x",
 
394
                           req->dh_group_id);
 
395
                ret->ignore = TRUE;
 
396
                return NULL;
 
397
        }
 
398
 
 
399
        if (req->public_key_id != EAP_PAX_PUBLIC_KEY_NONE) {
 
400
                wpa_printf(MSG_INFO, "EAP-PAX: Unsupported Public Key ID 0x%x",
 
401
                           req->public_key_id);
 
402
                ret->ignore = TRUE;
 
403
                return NULL;
 
404
        }
 
405
 
 
406
        if (req->flags & EAP_PAX_FLAGS_MF) {
 
407
                /* TODO: add support for reassembling fragments */
 
408
                wpa_printf(MSG_INFO, "EAP-PAX: fragmentation not supported - "
 
409
                           "ignored packet");
 
410
                ret->ignore = TRUE;
 
411
                return NULL;
 
412
        }
 
413
 
 
414
        icv = pos + len - EAP_PAX_ICV_LEN;
 
415
        wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", icv, EAP_PAX_ICV_LEN);
 
416
        if (req->op_code == EAP_PAX_OP_STD_1) {
 
417
                eap_pax_mac(req->mac_id, (u8 *) "", 0,
 
418
                            wpabuf_head(reqData), mlen, NULL, 0, NULL, 0,
 
419
                            icvbuf);
 
420
        } else {
 
421
                eap_pax_mac(req->mac_id, data->ick, EAP_PAX_ICK_LEN,
 
422
                            wpabuf_head(reqData), mlen, NULL, 0, NULL, 0,
 
423
                            icvbuf);
 
424
        }
 
425
        if (os_memcmp(icv, icvbuf, EAP_PAX_ICV_LEN) != 0) {
 
426
                wpa_printf(MSG_DEBUG, "EAP-PAX: invalid ICV - ignoring the "
 
427
                           "message");
 
428
                wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: expected ICV",
 
429
                            icvbuf, EAP_PAX_ICV_LEN);
 
430
                ret->ignore = TRUE;
 
431
                return NULL;
 
432
        }
 
433
 
 
434
        ret->ignore = FALSE;
 
435
        ret->methodState = METHOD_MAY_CONT;
 
436
        ret->decision = DECISION_FAIL;
 
437
        ret->allowNotifications = TRUE;
 
438
 
 
439
        switch (req->op_code) {
 
440
        case EAP_PAX_OP_STD_1:
 
441
                resp = eap_pax_process_std_1(data, ret, id, req, flen);
 
442
                break;
 
443
        case EAP_PAX_OP_STD_3:
 
444
                resp = eap_pax_process_std_3(data, ret, id, req, flen);
 
445
                break;
 
446
        default:
 
447
                wpa_printf(MSG_DEBUG, "EAP-PAX: ignoring message with unknown "
 
448
                           "op_code %d", req->op_code);
 
449
                ret->ignore = TRUE;
 
450
                return NULL;
 
451
        }
 
452
 
 
453
        if (ret->methodState == METHOD_DONE) {
 
454
                ret->allowNotifications = FALSE;
 
455
        }
 
456
 
 
457
        return resp;
 
458
}
 
459
 
 
460
 
 
461
static Boolean eap_pax_isKeyAvailable(struct eap_sm *sm, void *priv)
 
462
{
 
463
        struct eap_pax_data *data = priv;
 
464
        return data->state == PAX_DONE;
 
465
}
 
466
 
 
467
 
 
468
static u8 * eap_pax_getKey(struct eap_sm *sm, void *priv, size_t *len)
 
469
{
 
470
        struct eap_pax_data *data = priv;
 
471
        u8 *key;
 
472
 
 
473
        if (data->state != PAX_DONE)
 
474
                return NULL;
 
475
 
 
476
        key = os_malloc(EAP_MSK_LEN);
 
477
        if (key == NULL)
 
478
                return NULL;
 
479
 
 
480
        *len = EAP_MSK_LEN;
 
481
        eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN,
 
482
                    "Master Session Key", data->rand.e, 2 * EAP_PAX_RAND_LEN,
 
483
                    EAP_MSK_LEN, key);
 
484
 
 
485
        return key;
 
486
}
 
487
 
 
488
 
 
489
static u8 * eap_pax_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
 
490
{
 
491
        struct eap_pax_data *data = priv;
 
492
        u8 *key;
 
493
 
 
494
        if (data->state != PAX_DONE)
 
495
                return NULL;
 
496
 
 
497
        key = os_malloc(EAP_EMSK_LEN);
 
498
        if (key == NULL)
 
499
                return NULL;
 
500
 
 
501
        *len = EAP_EMSK_LEN;
 
502
        eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN,
 
503
                    "Extended Master Session Key",
 
504
                    data->rand.e, 2 * EAP_PAX_RAND_LEN,
 
505
                    EAP_EMSK_LEN, key);
 
506
 
 
507
        return key;
 
508
}
 
509
 
 
510
 
 
511
int eap_peer_pax_register(void)
 
512
{
 
513
        struct eap_method *eap;
 
514
        int ret;
 
515
 
 
516
        eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
 
517
                                    EAP_VENDOR_IETF, EAP_TYPE_PAX, "PAX");
 
518
        if (eap == NULL)
 
519
                return -1;
 
520
 
 
521
        eap->init = eap_pax_init;
 
522
        eap->deinit = eap_pax_deinit;
 
523
        eap->process = eap_pax_process;
 
524
        eap->isKeyAvailable = eap_pax_isKeyAvailable;
 
525
        eap->getKey = eap_pax_getKey;
 
526
        eap->get_emsk = eap_pax_get_emsk;
 
527
 
 
528
        ret = eap_peer_method_register(eap);
 
529
        if (ret)
 
530
                eap_peer_method_free(eap);
 
531
        return ret;
 
532
}