~ubuntu-branches/ubuntu/hardy/wpasupplicant/hardy

« back to all changes in this revision

Viewing changes to eap_gpsk.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler, Alexander Sack
  • Date: 2007-08-26 16:06:57 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20070826160657-2m8pxoweuxe8f93t
Tags: 0.6.0+0.5.8-0ubuntu1
* New upstream release
* remove patch 11_erroneous_manpage_ref, applied upstream
* remove patch 25_wpas_dbus_unregister_iface_fix, applied upstream

[ Alexander Sack ]
* bumping upstream version to replace development version 0.6.0 with
  this package from stable release branch.
* attempt to fix wierd timeout and high latency issues by going
  back to stable upstream version (0.5.9) (LP: #140763,
  LP: #141233).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * EAP peer method: EAP-GPSK (draft-ietf-emu-eap-gpsk-03.txt)
 
3
 * Copyright (c) 2006-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_i.h"
 
19
#include "config_ssid.h"
 
20
#include "eap_gpsk_common.h"
 
21
 
 
22
struct eap_gpsk_data {
 
23
        enum { GPSK_1, GPSK_3, SUCCESS, FAILURE } state;
 
24
        u8 rand_server[EAP_GPSK_RAND_LEN];
 
25
        u8 rand_client[EAP_GPSK_RAND_LEN];
 
26
        u8 msk[EAP_MSK_LEN];
 
27
        u8 emsk[EAP_EMSK_LEN];
 
28
        u8 sk[EAP_GPSK_MAX_SK_LEN];
 
29
        size_t sk_len;
 
30
        u8 pk[EAP_GPSK_MAX_PK_LEN];
 
31
        size_t pk_len;
 
32
        u8 session_id;
 
33
        int session_id_set;
 
34
        u8 *id_client;
 
35
        size_t id_client_len;
 
36
        u8 *id_server;
 
37
        size_t id_server_len;
 
38
        int vendor; /* CSuite/Specifier */
 
39
        int specifier; /* CSuite/Specifier */
 
40
        u8 *psk;
 
41
        size_t psk_len;
 
42
};
 
43
 
 
44
 
 
45
#ifndef CONFIG_NO_STDOUT_DEBUG
 
46
static const char * eap_gpsk_state_txt(int state)
 
47
{
 
48
        switch (state) {
 
49
        case GPSK_1:
 
50
                return "GPSK-1";
 
51
        case GPSK_3:
 
52
                return "GPSK-3";
 
53
        case SUCCESS:
 
54
                return "SUCCESS";
 
55
        case FAILURE:
 
56
                return "FAILURE";
 
57
        default:
 
58
                return "?";
 
59
        }
 
60
}
 
61
#endif /* CONFIG_NO_STDOUT_DEBUG */
 
62
 
 
63
 
 
64
static void eap_gpsk_state(struct eap_gpsk_data *data, int state)
 
65
{
 
66
        wpa_printf(MSG_DEBUG, "EAP-GPSK: %s -> %s",
 
67
                   eap_gpsk_state_txt(data->state),
 
68
                   eap_gpsk_state_txt(state));
 
69
        data->state = state;
 
70
}
 
71
 
 
72
 
 
73
static void eap_gpsk_deinit(struct eap_sm *sm, void *priv);
 
74
 
 
75
 
 
76
static void * eap_gpsk_init(struct eap_sm *sm)
 
77
{
 
78
        struct wpa_ssid *config = eap_get_config(sm);
 
79
        struct eap_gpsk_data *data;
 
80
 
 
81
        if (config == NULL) {
 
82
                wpa_printf(MSG_INFO, "EAP-GPSK: No configuration found");
 
83
                return NULL;
 
84
        }
 
85
 
 
86
        if (config->eappsk == NULL) {
 
87
                wpa_printf(MSG_INFO, "EAP-GPSK: No key (eappsk) configured");
 
88
                return NULL;
 
89
        }
 
90
 
 
91
        data = os_zalloc(sizeof(*data));
 
92
        if (data == NULL)
 
93
                return NULL;
 
94
        data->state = GPSK_1;
 
95
 
 
96
        if (config->nai) {
 
97
                data->id_client = os_malloc(config->nai_len);
 
98
                if (data->id_client == NULL) {
 
99
                        eap_gpsk_deinit(sm, data);
 
100
                        return NULL;
 
101
                }
 
102
                os_memcpy(data->id_client, config->nai, config->nai_len);
 
103
                data->id_client_len = config->nai_len;
 
104
        }
 
105
 
 
106
        data->psk = os_malloc(config->eappsk_len);
 
107
        if (data->psk == NULL) {
 
108
                eap_gpsk_deinit(sm, data);
 
109
                return NULL;
 
110
        }
 
111
        os_memcpy(data->psk, config->eappsk, config->eappsk_len);
 
112
        data->psk_len = config->eappsk_len;
 
113
 
 
114
        return data;
 
115
}
 
116
 
 
117
 
 
118
static void eap_gpsk_deinit(struct eap_sm *sm, void *priv)
 
119
{
 
120
        struct eap_gpsk_data *data = priv;
 
121
        os_free(data->id_server);
 
122
        os_free(data->id_client);
 
123
        os_free(data->psk);
 
124
        os_free(data);
 
125
}
 
126
 
 
127
 
 
128
static u8 * eap_gpsk_process_gpsk_1(struct eap_sm *sm,
 
129
                                    struct eap_gpsk_data *data,
 
130
                                    struct eap_method_ret *ret,
 
131
                                    const u8 *reqData, size_t reqDataLen,
 
132
                                    const u8 *payload, size_t payload_len,
 
133
                                    size_t *respDataLen)
 
134
{
 
135
        size_t len, csuite_list_len, miclen;
 
136
        struct eap_hdr *resp;
 
137
        u8 *rpos, *start;
 
138
        const u8 *csuite_list, *pos, *end;
 
139
        const struct eap_hdr *req;
 
140
        struct eap_gpsk_csuite *csuite;
 
141
        u16 alen;
 
142
        int i, count;
 
143
 
 
144
        if (data->state != GPSK_1) {
 
145
                ret->ignore = TRUE;
 
146
                return NULL;
 
147
        }
 
148
 
 
149
        wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Request/GPSK-1");
 
150
 
 
151
        req = (const struct eap_hdr *) reqData;
 
152
        pos = payload;
 
153
        end = payload + payload_len;
 
154
 
 
155
        if (end - pos < 2) {
 
156
                wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short GPSK-1 packet");
 
157
                return NULL;
 
158
        }
 
159
        alen = WPA_GET_BE16(pos);
 
160
        pos += 2;
 
161
        if (end - pos < alen) {
 
162
                wpa_printf(MSG_DEBUG, "EAP-GPSK: ID_Server overflow");
 
163
                return NULL;
 
164
        }
 
165
        os_free(data->id_server);
 
166
        data->id_server = os_malloc(alen);
 
167
        if (data->id_server == NULL) {
 
168
                wpa_printf(MSG_DEBUG, "EAP-GPSK: No memory for ID_Server");
 
169
                return NULL;
 
170
        }
 
171
        os_memcpy(data->id_server, pos, alen);
 
172
        data->id_server_len = alen;
 
173
        wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server",
 
174
                          data->id_server, data->id_server_len);
 
175
        pos += alen;
 
176
 
 
177
        if (end - pos < EAP_GPSK_RAND_LEN) {
 
178
                wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server overflow");
 
179
                return NULL;
 
180
        }
 
181
        os_memcpy(data->rand_server, pos, EAP_GPSK_RAND_LEN);
 
182
        wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server",
 
183
                    data->rand_server, EAP_GPSK_RAND_LEN);
 
184
        pos += EAP_GPSK_RAND_LEN;
 
185
 
 
186
        if (end - pos < 2) {
 
187
                wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short GPSK-1 packet");
 
188
                return NULL;
 
189
        }
 
190
        csuite_list_len = WPA_GET_BE16(pos);
 
191
        pos += 2;
 
192
        if (end - pos < (int) csuite_list_len) {
 
193
                wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_List overflow");
 
194
                return NULL;
 
195
        }
 
196
        csuite_list = pos;
 
197
 
 
198
        if (csuite_list_len == 0 ||
 
199
            csuite_list_len % sizeof(struct eap_gpsk_csuite)) {
 
200
                wpa_printf(MSG_DEBUG, "EAP-GPSK: Invalid CSuite_List len %d",
 
201
                           csuite_list_len);
 
202
                return NULL;
 
203
        }
 
204
        count = csuite_list_len / sizeof(struct eap_gpsk_csuite);
 
205
        data->vendor = EAP_GPSK_VENDOR_IETF;
 
206
        data->specifier = EAP_GPSK_CIPHER_RESERVED;
 
207
        csuite = (struct eap_gpsk_csuite *) csuite_list;
 
208
        for (i = 0; i < count; i++) {
 
209
                int vendor, specifier;
 
210
                vendor = WPA_GET_BE24(csuite->vendor);
 
211
                specifier = WPA_GET_BE24(csuite->specifier);
 
212
                wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite[%d]: %d:%d",
 
213
                           i, vendor, specifier);
 
214
                if (data->vendor == EAP_GPSK_VENDOR_IETF &&
 
215
                    data->specifier == EAP_GPSK_CIPHER_RESERVED &&
 
216
                    eap_gpsk_supported_ciphersuite(vendor, specifier)) {
 
217
                        data->vendor = vendor;
 
218
                        data->specifier = specifier;
 
219
                }
 
220
                csuite++;
 
221
        }
 
222
        if (data->vendor == EAP_GPSK_VENDOR_IETF &&
 
223
            data->specifier == EAP_GPSK_CIPHER_RESERVED) {
 
224
                wpa_msg(sm->msg_ctx, MSG_INFO, "EAP-GPSK: No supported "
 
225
                        "ciphersuite found");
 
226
                eap_gpsk_state(data, FAILURE);
 
227
                return NULL;
 
228
        }
 
229
        wpa_printf(MSG_DEBUG, "EAP-GPSK: Selected ciphersuite %d:%d",
 
230
                   data->vendor, data->specifier);
 
231
 
 
232
        wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-2");
 
233
 
 
234
        miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
 
235
        len = 1 + 2 + data->id_client_len + 2 + data->id_server_len +
 
236
                2 * EAP_GPSK_RAND_LEN + 2 + csuite_list_len +
 
237
                sizeof(struct eap_gpsk_csuite) + 2 + miclen;
 
238
 
 
239
        resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respDataLen, len,
 
240
                             EAP_CODE_RESPONSE, req->identifier, &rpos);
 
241
        if (resp == NULL)
 
242
                return NULL;
 
243
 
 
244
        *rpos++ = EAP_GPSK_OPCODE_GPSK_2;
 
245
        start = rpos;
 
246
 
 
247
        wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Client",
 
248
                          data->id_client, data->id_client_len);
 
249
        WPA_PUT_BE16(rpos, data->id_client_len);
 
250
        rpos += 2;
 
251
        if (data->id_client)
 
252
                os_memcpy(rpos, data->id_client, data->id_client_len);
 
253
        rpos += data->id_client_len;
 
254
 
 
255
        WPA_PUT_BE16(rpos, data->id_server_len);
 
256
        rpos += 2;
 
257
        if (data->id_server)
 
258
                os_memcpy(rpos, data->id_server, data->id_server_len);
 
259
        rpos += data->id_server_len;
 
260
 
 
261
        if (os_get_random(data->rand_client, EAP_GPSK_RAND_LEN)) {
 
262
                wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to get random data "
 
263
                           "for RAND_Client");
 
264
                eap_gpsk_state(data, FAILURE);
 
265
                os_free(resp);
 
266
                return NULL;
 
267
        }
 
268
        wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Client",
 
269
                    data->rand_client, EAP_GPSK_RAND_LEN);
 
270
        os_memcpy(rpos, data->rand_client, EAP_GPSK_RAND_LEN);
 
271
        rpos += EAP_GPSK_RAND_LEN;
 
272
 
 
273
        os_memcpy(rpos, data->rand_server, EAP_GPSK_RAND_LEN);
 
274
        rpos += EAP_GPSK_RAND_LEN;
 
275
 
 
276
        WPA_PUT_BE16(rpos, csuite_list_len);
 
277
        rpos += 2;
 
278
        os_memcpy(rpos, csuite_list, csuite_list_len);
 
279
        rpos += csuite_list_len;
 
280
 
 
281
        csuite = (struct eap_gpsk_csuite *) rpos;
 
282
        WPA_PUT_BE24(csuite->vendor, data->vendor);
 
283
        WPA_PUT_BE24(csuite->specifier, data->specifier);
 
284
        rpos = (u8 *) (csuite + 1);
 
285
 
 
286
        if (eap_gpsk_derive_keys(data->psk, data->psk_len,
 
287
                                 data->vendor, data->specifier,
 
288
                                 data->rand_client, data->rand_server,
 
289
                                 data->id_client, data->id_client_len,
 
290
                                 data->id_server, data->id_server_len,
 
291
                                 data->msk, data->emsk,
 
292
                                 data->sk, &data->sk_len,
 
293
                                 data->pk, &data->pk_len) < 0) {
 
294
                wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive keys");
 
295
                eap_gpsk_state(data, FAILURE);
 
296
                os_free(resp);
 
297
                return NULL;
 
298
        }
 
299
 
 
300
        /* No PD_Payload_1 */
 
301
        WPA_PUT_BE16(rpos, 0);
 
302
        rpos += 2;
 
303
 
 
304
        if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
 
305
                                 data->specifier, start, rpos - start, rpos) <
 
306
            0) {
 
307
                eap_gpsk_state(data, FAILURE);
 
308
                os_free(resp);
 
309
                return NULL;
 
310
        }
 
311
 
 
312
        eap_gpsk_state(data, GPSK_3);
 
313
 
 
314
        return (u8 *) resp;
 
315
}
 
316
 
 
317
 
 
318
static u8 * eap_gpsk_process_gpsk_3(struct eap_sm *sm,
 
319
                                    struct eap_gpsk_data *data,
 
320
                                    struct eap_method_ret *ret,
 
321
                                    const u8 *reqData, size_t reqDataLen,
 
322
                                    const u8 *payload, size_t payload_len,
 
323
                                    size_t *respDataLen)
 
324
{
 
325
        size_t len, miclen;
 
326
        struct eap_hdr *resp;
 
327
        u8 *rpos, *start;
 
328
        const struct eap_hdr *req;
 
329
        const u8 *pos, *end;
 
330
        u16 alen;
 
331
        int vendor, specifier;
 
332
        const struct eap_gpsk_csuite *csuite;
 
333
        u8 mic[EAP_GPSK_MAX_MIC_LEN];
 
334
 
 
335
        if (data->state != GPSK_3) {
 
336
                ret->ignore = TRUE;
 
337
                return NULL;
 
338
        }
 
339
 
 
340
        wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Request/GPSK-3");
 
341
 
 
342
        req = (const struct eap_hdr *) reqData;
 
343
        pos = payload;
 
344
        end = payload + payload_len;
 
345
 
 
346
        if (end - pos < EAP_GPSK_RAND_LEN) {
 
347
                wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
 
348
                           "RAND_Client");
 
349
                return NULL;
 
350
        }
 
351
        if (os_memcmp(pos, data->rand_client, EAP_GPSK_RAND_LEN) != 0) {
 
352
                wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Client in GPSK-2 and "
 
353
                           "GPSK-3 did not match");
 
354
                wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Client in GPSK-2",
 
355
                            data->rand_client, EAP_GPSK_RAND_LEN);
 
356
                wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Client in GPSK-3",
 
357
                            pos, EAP_GPSK_RAND_LEN);
 
358
                eap_gpsk_state(data, FAILURE);
 
359
                return NULL;
 
360
        }
 
361
        pos += EAP_GPSK_RAND_LEN;
 
362
 
 
363
        if (end - pos < EAP_GPSK_RAND_LEN) {
 
364
                wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
 
365
                           "RAND_Server");
 
366
                return NULL;
 
367
        }
 
368
        if (os_memcmp(pos, data->rand_server, EAP_GPSK_RAND_LEN) != 0) {
 
369
                wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1 and "
 
370
                           "GPSK-3 did not match");
 
371
                wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1",
 
372
                            data->rand_server, EAP_GPSK_RAND_LEN);
 
373
                wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-3",
 
374
                            pos, EAP_GPSK_RAND_LEN);
 
375
                eap_gpsk_state(data, FAILURE);
 
376
                return NULL;
 
377
        }
 
378
        pos += EAP_GPSK_RAND_LEN;
 
379
 
 
380
        if (end - pos < (int) sizeof(*csuite)) {
 
381
                wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
 
382
                           "CSuite_Sel");
 
383
                return NULL;
 
384
        }
 
385
        csuite = (const struct eap_gpsk_csuite *) pos;
 
386
        vendor = WPA_GET_BE24(csuite->vendor);
 
387
        specifier = WPA_GET_BE24(csuite->specifier);
 
388
        pos += sizeof(*csuite);
 
389
        if (vendor != data->vendor || specifier != data->specifier) {
 
390
                wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel (%d:%d) does not "
 
391
                           "match with the one sent in GPSK-2 (%d:%d)",
 
392
                           vendor, specifier, data->vendor, data->specifier);
 
393
                eap_gpsk_state(data, FAILURE);
 
394
                return NULL;
 
395
        }
 
396
 
 
397
        if (end - pos < 2) {
 
398
                wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
 
399
                           "PD_Payload_2 length");
 
400
                eap_gpsk_state(data, FAILURE);
 
401
                return NULL;
 
402
        }
 
403
        alen = WPA_GET_BE16(pos);
 
404
        pos += 2;
 
405
        if (end - pos < alen) {
 
406
                wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
 
407
                           "%d-octet PD_Payload_2", alen);
 
408
                eap_gpsk_state(data, FAILURE);
 
409
                return NULL;
 
410
        }
 
411
        wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_2", pos, alen);
 
412
        pos += alen;
 
413
        miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
 
414
        if (end - pos < (int) miclen) {
 
415
                wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC "
 
416
                           "(left=%d miclen=%d)", end - pos, miclen);
 
417
                eap_gpsk_state(data, FAILURE);
 
418
                return NULL;
 
419
        }
 
420
        if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
 
421
                                 data->specifier, payload, pos - payload, mic)
 
422
            < 0) {
 
423
                wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC");
 
424
                eap_gpsk_state(data, FAILURE);
 
425
                return NULL;
 
426
        }
 
427
        if (os_memcmp(mic, pos, miclen) != 0) {
 
428
                wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-3");
 
429
                wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen);
 
430
                wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen);
 
431
                eap_gpsk_state(data, FAILURE);
 
432
                return NULL;
 
433
        }
 
434
        pos += miclen;
 
435
 
 
436
        if (pos != end) {
 
437
                wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %d bytes of extra "
 
438
                           "data in the end of GPSK-2", end - pos);
 
439
        }
 
440
 
 
441
        wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-4");
 
442
 
 
443
        len = 1 + 2 + miclen;
 
444
 
 
445
        resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respDataLen, len,
 
446
                             EAP_CODE_RESPONSE, req->identifier, &rpos);
 
447
        if (resp == NULL)
 
448
                return NULL;
 
449
 
 
450
        *rpos++ = EAP_GPSK_OPCODE_GPSK_4;
 
451
        start = rpos;
 
452
 
 
453
        /* No PD_Payload_3 */
 
454
        WPA_PUT_BE16(rpos, 0);
 
455
        rpos += 2;
 
456
 
 
457
        if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
 
458
                                 data->specifier, start, rpos - start, rpos) <
 
459
            0) {
 
460
                eap_gpsk_state(data, FAILURE);
 
461
                os_free(resp);
 
462
                return NULL;
 
463
        }
 
464
 
 
465
        eap_gpsk_state(data, SUCCESS);
 
466
        ret->methodState = METHOD_DONE;
 
467
        ret->decision = DECISION_UNCOND_SUCC;
 
468
 
 
469
        return (u8 *) resp;
 
470
}
 
471
 
 
472
 
 
473
static u8 * eap_gpsk_process(struct eap_sm *sm, void *priv,
 
474
                            struct eap_method_ret *ret,
 
475
                            const u8 *reqData, size_t reqDataLen,
 
476
                            size_t *respDataLen)
 
477
{
 
478
        struct eap_gpsk_data *data = priv;
 
479
        u8 *resp;
 
480
        const u8 *pos;
 
481
        size_t len;
 
482
 
 
483
        pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK,
 
484
                               reqData, reqDataLen, &len);
 
485
        if (pos == NULL || len < 1) {
 
486
                ret->ignore = TRUE;
 
487
                return NULL;
 
488
        }
 
489
 
 
490
        wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode %d", *pos);
 
491
 
 
492
        ret->ignore = FALSE;
 
493
        ret->methodState = METHOD_MAY_CONT;
 
494
        ret->decision = DECISION_FAIL;
 
495
        ret->allowNotifications = FALSE;
 
496
 
 
497
        switch (*pos) {
 
498
        case EAP_GPSK_OPCODE_GPSK_1:
 
499
                resp = eap_gpsk_process_gpsk_1(sm, data, ret, reqData,
 
500
                                               reqDataLen, pos + 1, len - 1,
 
501
                                               respDataLen);
 
502
                break;
 
503
        case EAP_GPSK_OPCODE_GPSK_3:
 
504
                resp = eap_gpsk_process_gpsk_3(sm, data, ret, reqData,
 
505
                                               reqDataLen, pos + 1, len - 1,
 
506
                                               respDataLen);
 
507
                break;
 
508
        default:
 
509
                wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignoring message with "
 
510
                           "unknown opcode %d", *pos);
 
511
                ret->ignore = TRUE;
 
512
                return NULL;
 
513
        }
 
514
 
 
515
        return resp;
 
516
}
 
517
 
 
518
 
 
519
static Boolean eap_gpsk_isKeyAvailable(struct eap_sm *sm, void *priv)
 
520
{
 
521
        struct eap_gpsk_data *data = priv;
 
522
        return data->state == SUCCESS;
 
523
}
 
524
 
 
525
 
 
526
static u8 * eap_gpsk_getKey(struct eap_sm *sm, void *priv, size_t *len)
 
527
{
 
528
        struct eap_gpsk_data *data = priv;
 
529
        u8 *key;
 
530
 
 
531
        if (data->state != SUCCESS)
 
532
                return NULL;
 
533
 
 
534
        key = os_malloc(EAP_MSK_LEN);
 
535
        if (key == NULL)
 
536
                return NULL;
 
537
        os_memcpy(key, data->msk, EAP_MSK_LEN);
 
538
        *len = EAP_MSK_LEN;
 
539
 
 
540
        return key;
 
541
}
 
542
 
 
543
 
 
544
static u8 * eap_gpsk_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
 
545
{
 
546
        struct eap_gpsk_data *data = priv;
 
547
        u8 *key;
 
548
 
 
549
        if (data->state != SUCCESS)
 
550
                return NULL;
 
551
 
 
552
        key = os_malloc(EAP_EMSK_LEN);
 
553
        if (key == NULL)
 
554
                return NULL;
 
555
        os_memcpy(key, data->emsk, EAP_EMSK_LEN);
 
556
        *len = EAP_EMSK_LEN;
 
557
 
 
558
        return key;
 
559
}
 
560
 
 
561
 
 
562
int eap_peer_gpsk_register(void)
 
563
{
 
564
        struct eap_method *eap;
 
565
        int ret;
 
566
 
 
567
        eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
 
568
                                    EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK");
 
569
        if (eap == NULL)
 
570
                return -1;
 
571
 
 
572
        eap->init = eap_gpsk_init;
 
573
        eap->deinit = eap_gpsk_deinit;
 
574
        eap->process = eap_gpsk_process;
 
575
        eap->isKeyAvailable = eap_gpsk_isKeyAvailable;
 
576
        eap->getKey = eap_gpsk_getKey;
 
577
        eap->get_emsk = eap_gpsk_get_emsk;
 
578
 
 
579
        ret = eap_peer_method_register(eap);
 
580
        if (ret)
 
581
                eap_peer_method_free(eap);
 
582
        return ret;
 
583
}