~ubuntu-branches/ubuntu/lucid/wpasupplicant/lucid-security

« back to all changes in this revision

Viewing changes to src/eap_server/eap_pax.c

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

Show diffs side-by-side

added added

removed removed

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