]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/wpa/src/eap_server/eap_server_gpsk.c
Update hostapd/wpa_supplicant to 2.8 to fix multiple vulnerabilities.
[FreeBSD/FreeBSD.git] / contrib / wpa / src / eap_server / eap_server_gpsk.c
1 /*
2  * hostapd / EAP-GPSK (RFC 5433) server
3  * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8
9 #include "includes.h"
10
11 #include "common.h"
12 #include "crypto/random.h"
13 #include "eap_server/eap_i.h"
14 #include "eap_common/eap_gpsk_common.h"
15
16
17 struct eap_gpsk_data {
18         enum { GPSK_1, GPSK_3, SUCCESS, FAILURE } state;
19         u8 rand_server[EAP_GPSK_RAND_LEN];
20         u8 rand_peer[EAP_GPSK_RAND_LEN];
21         u8 msk[EAP_MSK_LEN];
22         u8 emsk[EAP_EMSK_LEN];
23         u8 sk[EAP_GPSK_MAX_SK_LEN];
24         size_t sk_len;
25         u8 pk[EAP_GPSK_MAX_PK_LEN];
26         size_t pk_len;
27         u8 session_id[128];
28         size_t id_len;
29         u8 *id_peer;
30         size_t id_peer_len;
31 #define MAX_NUM_CSUITES 2
32         struct eap_gpsk_csuite csuite_list[MAX_NUM_CSUITES];
33         size_t csuite_count;
34         int vendor; /* CSuite/Vendor */
35         int specifier; /* CSuite/Specifier */
36 };
37
38
39 static const char * eap_gpsk_state_txt(int state)
40 {
41         switch (state) {
42         case GPSK_1:
43                 return "GPSK-1";
44         case GPSK_3:
45                 return "GPSK-3";
46         case SUCCESS:
47                 return "SUCCESS";
48         case FAILURE:
49                 return "FAILURE";
50         default:
51                 return "?";
52         }
53 }
54
55
56 static void eap_gpsk_state(struct eap_gpsk_data *data, int state)
57 {
58         wpa_printf(MSG_DEBUG, "EAP-GPSK: %s -> %s",
59                    eap_gpsk_state_txt(data->state),
60                    eap_gpsk_state_txt(state));
61         data->state = state;
62 }
63
64
65 static void * eap_gpsk_init(struct eap_sm *sm)
66 {
67         struct eap_gpsk_data *data;
68
69         data = os_zalloc(sizeof(*data));
70         if (data == NULL)
71                 return NULL;
72         data->state = GPSK_1;
73
74         data->csuite_count = 0;
75         if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF,
76                                            EAP_GPSK_CIPHER_AES)) {
77                 WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor,
78                              EAP_GPSK_VENDOR_IETF);
79                 WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier,
80                              EAP_GPSK_CIPHER_AES);
81                 data->csuite_count++;
82         }
83         if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF,
84                                            EAP_GPSK_CIPHER_SHA256)) {
85                 WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor,
86                              EAP_GPSK_VENDOR_IETF);
87                 WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier,
88                              EAP_GPSK_CIPHER_SHA256);
89                 data->csuite_count++;
90         }
91
92         return data;
93 }
94
95
96 static void eap_gpsk_reset(struct eap_sm *sm, void *priv)
97 {
98         struct eap_gpsk_data *data = priv;
99         os_free(data->id_peer);
100         bin_clear_free(data, sizeof(*data));
101 }
102
103
104 static struct wpabuf * eap_gpsk_build_gpsk_1(struct eap_sm *sm,
105                                              struct eap_gpsk_data *data, u8 id)
106 {
107         size_t len;
108         struct wpabuf *req;
109
110         wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-1");
111
112         if (random_get_bytes(data->rand_server, EAP_GPSK_RAND_LEN)) {
113                 wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to get random data");
114                 eap_gpsk_state(data, FAILURE);
115                 return NULL;
116         }
117         wpa_hexdump(MSG_MSGDUMP, "EAP-GPSK: RAND_Server",
118                     data->rand_server, EAP_GPSK_RAND_LEN);
119
120         len = 1 + 2 + sm->server_id_len + EAP_GPSK_RAND_LEN + 2 +
121                 data->csuite_count * sizeof(struct eap_gpsk_csuite);
122         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len,
123                             EAP_CODE_REQUEST, id);
124         if (req == NULL) {
125                 wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to allocate memory "
126                            "for request/GPSK-1");
127                 eap_gpsk_state(data, FAILURE);
128                 return NULL;
129         }
130
131         wpabuf_put_u8(req, EAP_GPSK_OPCODE_GPSK_1);
132         wpabuf_put_be16(req, sm->server_id_len);
133         wpabuf_put_data(req, sm->server_id, sm->server_id_len);
134         wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN);
135         wpabuf_put_be16(req,
136                         data->csuite_count * sizeof(struct eap_gpsk_csuite));
137         wpabuf_put_data(req, data->csuite_list,
138                         data->csuite_count * sizeof(struct eap_gpsk_csuite));
139
140         return req;
141 }
142
143
144 static struct wpabuf * eap_gpsk_build_gpsk_3(struct eap_sm *sm,
145                                              struct eap_gpsk_data *data, u8 id)
146 {
147         u8 *pos, *start;
148         size_t len, miclen;
149         struct eap_gpsk_csuite *csuite;
150         struct wpabuf *req;
151
152         wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-3");
153
154         miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
155         len = 1 + 2 * EAP_GPSK_RAND_LEN + 2 + sm->server_id_len +
156                 sizeof(struct eap_gpsk_csuite) + 2 + miclen;
157         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len,
158                             EAP_CODE_REQUEST, id);
159         if (req == NULL) {
160                 wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to allocate memory "
161                            "for request/GPSK-3");
162                 eap_gpsk_state(data, FAILURE);
163                 return NULL;
164         }
165
166         wpabuf_put_u8(req, EAP_GPSK_OPCODE_GPSK_3);
167         start = wpabuf_put(req, 0);
168
169         wpabuf_put_data(req, data->rand_peer, EAP_GPSK_RAND_LEN);
170         wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN);
171         wpabuf_put_be16(req, sm->server_id_len);
172         wpabuf_put_data(req, sm->server_id, sm->server_id_len);
173         csuite = wpabuf_put(req, sizeof(*csuite));
174         WPA_PUT_BE32(csuite->vendor, data->vendor);
175         WPA_PUT_BE16(csuite->specifier, data->specifier);
176
177         /* no PD_Payload_2 */
178         wpabuf_put_be16(req, 0);
179
180         pos = wpabuf_put(req, miclen);
181         if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
182                                  data->specifier, start, pos - start, pos) < 0)
183         {
184                 wpabuf_free(req);
185                 eap_gpsk_state(data, FAILURE);
186                 return NULL;
187         }
188
189         return req;
190 }
191
192
193 static struct wpabuf * eap_gpsk_buildReq(struct eap_sm *sm, void *priv, u8 id)
194 {
195         struct eap_gpsk_data *data = priv;
196
197         switch (data->state) {
198         case GPSK_1:
199                 return eap_gpsk_build_gpsk_1(sm, data, id);
200         case GPSK_3:
201                 return eap_gpsk_build_gpsk_3(sm, data, id);
202         default:
203                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Unknown state %d in buildReq",
204                            data->state);
205                 break;
206         }
207         return NULL;
208 }
209
210
211 static Boolean eap_gpsk_check(struct eap_sm *sm, void *priv,
212                               struct wpabuf *respData)
213 {
214         struct eap_gpsk_data *data = priv;
215         const u8 *pos;
216         size_t len;
217
218         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respData, &len);
219         if (pos == NULL || len < 1) {
220                 wpa_printf(MSG_INFO, "EAP-GPSK: Invalid frame");
221                 return TRUE;
222         }
223
224         wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode=%d", *pos);
225
226         if (data->state == GPSK_1 && *pos == EAP_GPSK_OPCODE_GPSK_2)
227                 return FALSE;
228
229         if (data->state == GPSK_3 && *pos == EAP_GPSK_OPCODE_GPSK_4)
230                 return FALSE;
231
232         wpa_printf(MSG_INFO, "EAP-GPSK: Unexpected opcode=%d in state=%d",
233                    *pos, data->state);
234
235         return TRUE;
236 }
237
238
239 static void eap_gpsk_process_gpsk_2(struct eap_sm *sm,
240                                     struct eap_gpsk_data *data,
241                                     const u8 *payload, size_t payloadlen)
242 {
243         const u8 *pos, *end;
244         u16 alen;
245         const struct eap_gpsk_csuite *csuite;
246         size_t i, miclen;
247         u8 mic[EAP_GPSK_MAX_MIC_LEN];
248
249         if (data->state != GPSK_1)
250                 return;
251
252         wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Response/GPSK-2");
253
254         pos = payload;
255         end = payload + payloadlen;
256
257         if (end - pos < 2) {
258                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
259                            "ID_Peer length");
260                 eap_gpsk_state(data, FAILURE);
261                 return;
262         }
263         alen = WPA_GET_BE16(pos);
264         pos += 2;
265         if (end - pos < alen) {
266                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
267                            "ID_Peer");
268                 eap_gpsk_state(data, FAILURE);
269                 return;
270         }
271         os_free(data->id_peer);
272         data->id_peer = os_memdup(pos, alen);
273         if (data->id_peer == NULL) {
274                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Not enough memory to store "
275                            "%d-octet ID_Peer", alen);
276                 return;
277         }
278         data->id_peer_len = alen;
279         wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer",
280                           data->id_peer, data->id_peer_len);
281         pos += alen;
282
283         if (end - pos < 2) {
284                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
285                            "ID_Server length");
286                 eap_gpsk_state(data, FAILURE);
287                 return;
288         }
289         alen = WPA_GET_BE16(pos);
290         pos += 2;
291         if (end - pos < alen) {
292                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
293                            "ID_Server");
294                 eap_gpsk_state(data, FAILURE);
295                 return;
296         }
297         if (alen != sm->server_id_len ||
298             os_memcmp(pos, sm->server_id, alen) != 0) {
299                 wpa_printf(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-1 and "
300                            "GPSK-2 did not match");
301                 eap_gpsk_state(data, FAILURE);
302                 return;
303         }
304         pos += alen;
305
306         if (end - pos < EAP_GPSK_RAND_LEN) {
307                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
308                            "RAND_Peer");
309                 eap_gpsk_state(data, FAILURE);
310                 return;
311         }
312         os_memcpy(data->rand_peer, pos, EAP_GPSK_RAND_LEN);
313         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer",
314                     data->rand_peer, EAP_GPSK_RAND_LEN);
315         pos += EAP_GPSK_RAND_LEN;
316
317         if (end - pos < EAP_GPSK_RAND_LEN) {
318                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
319                            "RAND_Server");
320                 eap_gpsk_state(data, FAILURE);
321                 return;
322         }
323         if (os_memcmp(data->rand_server, pos, EAP_GPSK_RAND_LEN) != 0) {
324                 wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1 and "
325                            "GPSK-2 did not match");
326                 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1",
327                             data->rand_server, EAP_GPSK_RAND_LEN);
328                 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-2",
329                             pos, EAP_GPSK_RAND_LEN);
330                 eap_gpsk_state(data, FAILURE);
331                 return;
332         }
333         pos += EAP_GPSK_RAND_LEN;
334
335         if (end - pos < 2) {
336                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
337                            "CSuite_List length");
338                 eap_gpsk_state(data, FAILURE);
339                 return;
340         }
341         alen = WPA_GET_BE16(pos);
342         pos += 2;
343         if (end - pos < alen) {
344                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
345                            "CSuite_List");
346                 eap_gpsk_state(data, FAILURE);
347                 return;
348         }
349         if (alen != data->csuite_count * sizeof(struct eap_gpsk_csuite) ||
350             os_memcmp(pos, data->csuite_list, alen) != 0) {
351                 wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_List in GPSK-1 and "
352                            "GPSK-2 did not match");
353                 eap_gpsk_state(data, FAILURE);
354                 return;
355         }
356         pos += alen;
357
358         if (end - pos < (int) sizeof(*csuite)) {
359                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
360                            "CSuite_Sel");
361                 eap_gpsk_state(data, FAILURE);
362                 return;
363         }
364         csuite = (const struct eap_gpsk_csuite *) pos;
365         for (i = 0; i < data->csuite_count; i++) {
366                 if (os_memcmp(csuite, &data->csuite_list[i], sizeof(*csuite))
367                     == 0)
368                         break;
369         }
370         if (i == data->csuite_count) {
371                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Peer selected unsupported "
372                            "ciphersuite %d:%d",
373                            WPA_GET_BE32(csuite->vendor),
374                            WPA_GET_BE16(csuite->specifier));
375                 eap_gpsk_state(data, FAILURE);
376                 return;
377         }
378         data->vendor = WPA_GET_BE32(csuite->vendor);
379         data->specifier = WPA_GET_BE16(csuite->specifier);
380         wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel %d:%d",
381                    data->vendor, data->specifier);
382         pos += sizeof(*csuite);
383
384         if (end - pos < 2) {
385                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
386                            "PD_Payload_1 length");
387                 eap_gpsk_state(data, FAILURE);
388                 return;
389         }
390         alen = WPA_GET_BE16(pos);
391         pos += 2;
392         if (end - pos < alen) {
393                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
394                            "PD_Payload_1");
395                 eap_gpsk_state(data, FAILURE);
396                 return;
397         }
398         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_1", pos, alen);
399         pos += alen;
400
401         if (sm->user == NULL || sm->user->password == NULL) {
402                 wpa_printf(MSG_INFO, "EAP-GPSK: No PSK/password configured "
403                            "for the user");
404                 eap_gpsk_state(data, FAILURE);
405                 return;
406         }
407
408         if (eap_gpsk_derive_keys(sm->user->password, sm->user->password_len,
409                                  data->vendor, data->specifier,
410                                  data->rand_peer, data->rand_server,
411                                  data->id_peer, data->id_peer_len,
412                                  sm->server_id, sm->server_id_len,
413                                  data->msk, data->emsk,
414                                  data->sk, &data->sk_len,
415                                  data->pk, &data->pk_len) < 0) {
416                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive keys");
417                 eap_gpsk_state(data, FAILURE);
418                 return;
419         }
420
421         if (eap_gpsk_derive_session_id(sm->user->password,
422                                        sm->user->password_len,
423                                        data->vendor, data->specifier,
424                                        data->rand_peer, data->rand_server,
425                                        data->id_peer, data->id_peer_len,
426                                        sm->server_id, sm->server_id_len,
427                                        EAP_TYPE_GPSK,
428                                        data->session_id, &data->id_len) < 0) {
429                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive Session-Id");
430                 eap_gpsk_state(data, FAILURE);
431                 return;
432         }
433         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Derived Session-Id",
434                     data->session_id, data->id_len);
435
436         miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
437         if (end - pos < (int) miclen) {
438                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC "
439                            "(left=%lu miclen=%lu)",
440                            (unsigned long) (end - pos),
441                            (unsigned long) miclen);
442                 eap_gpsk_state(data, FAILURE);
443                 return;
444         }
445         if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
446                                  data->specifier, payload, pos - payload, mic)
447             < 0) {
448                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC");
449                 eap_gpsk_state(data, FAILURE);
450                 return;
451         }
452         if (os_memcmp_const(mic, pos, miclen) != 0) {
453                 wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-2");
454                 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen);
455                 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen);
456                 eap_gpsk_state(data, FAILURE);
457                 return;
458         }
459         pos += miclen;
460
461         if (pos != end) {
462                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra "
463                            "data in the end of GPSK-2",
464                            (unsigned long) (end - pos));
465         }
466
467         eap_gpsk_state(data, GPSK_3);
468 }
469
470
471 static void eap_gpsk_process_gpsk_4(struct eap_sm *sm,
472                                     struct eap_gpsk_data *data,
473                                     const u8 *payload, size_t payloadlen)
474 {
475         const u8 *pos, *end;
476         u16 alen;
477         size_t miclen;
478         u8 mic[EAP_GPSK_MAX_MIC_LEN];
479
480         if (data->state != GPSK_3)
481                 return;
482
483         wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Response/GPSK-4");
484
485         pos = payload;
486         end = payload + payloadlen;
487
488         if (end - pos < 2) {
489                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
490                            "PD_Payload_1 length");
491                 eap_gpsk_state(data, FAILURE);
492                 return;
493         }
494         alen = WPA_GET_BE16(pos);
495         pos += 2;
496         if (end - pos < alen) {
497                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
498                            "PD_Payload_1");
499                 eap_gpsk_state(data, FAILURE);
500                 return;
501         }
502         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_1", pos, alen);
503         pos += alen;
504
505         miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
506         if (end - pos < (int) miclen) {
507                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC "
508                            "(left=%lu miclen=%lu)",
509                            (unsigned long) (end - pos),
510                            (unsigned long) miclen);
511                 eap_gpsk_state(data, FAILURE);
512                 return;
513         }
514         if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
515                                  data->specifier, payload, pos - payload, mic)
516             < 0) {
517                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC");
518                 eap_gpsk_state(data, FAILURE);
519                 return;
520         }
521         if (os_memcmp_const(mic, pos, miclen) != 0) {
522                 wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-4");
523                 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen);
524                 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen);
525                 eap_gpsk_state(data, FAILURE);
526                 return;
527         }
528         pos += miclen;
529
530         if (pos != end) {
531                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra "
532                            "data in the end of GPSK-4",
533                            (unsigned long) (end - pos));
534         }
535
536         eap_gpsk_state(data, SUCCESS);
537 }
538
539
540 static void eap_gpsk_process(struct eap_sm *sm, void *priv,
541                              struct wpabuf *respData)
542 {
543         struct eap_gpsk_data *data = priv;
544         const u8 *pos;
545         size_t len;
546
547         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respData, &len);
548         if (pos == NULL || len < 1)
549                 return;
550
551         switch (*pos) {
552         case EAP_GPSK_OPCODE_GPSK_2:
553                 eap_gpsk_process_gpsk_2(sm, data, pos + 1, len - 1);
554                 break;
555         case EAP_GPSK_OPCODE_GPSK_4:
556                 eap_gpsk_process_gpsk_4(sm, data, pos + 1, len - 1);
557                 break;
558         }
559 }
560
561
562 static Boolean eap_gpsk_isDone(struct eap_sm *sm, void *priv)
563 {
564         struct eap_gpsk_data *data = priv;
565         return data->state == SUCCESS || data->state == FAILURE;
566 }
567
568
569 static u8 * eap_gpsk_getKey(struct eap_sm *sm, void *priv, size_t *len)
570 {
571         struct eap_gpsk_data *data = priv;
572         u8 *key;
573
574         if (data->state != SUCCESS)
575                 return NULL;
576
577         key = os_memdup(data->msk, EAP_MSK_LEN);
578         if (key == NULL)
579                 return NULL;
580         *len = EAP_MSK_LEN;
581
582         return key;
583 }
584
585
586 static u8 * eap_gpsk_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
587 {
588         struct eap_gpsk_data *data = priv;
589         u8 *key;
590
591         if (data->state != SUCCESS)
592                 return NULL;
593
594         key = os_memdup(data->emsk, EAP_EMSK_LEN);
595         if (key == NULL)
596                 return NULL;
597         *len = EAP_EMSK_LEN;
598
599         return key;
600 }
601
602
603 static Boolean eap_gpsk_isSuccess(struct eap_sm *sm, void *priv)
604 {
605         struct eap_gpsk_data *data = priv;
606         return data->state == SUCCESS;
607 }
608
609
610 static u8 * eap_gpsk_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
611 {
612         struct eap_gpsk_data *data = priv;
613         u8 *sid;
614
615         if (data->state != SUCCESS)
616                 return NULL;
617
618         sid = os_memdup(data->session_id, data->id_len);
619         if (sid == NULL)
620                 return NULL;
621         *len = data->id_len;
622
623         return sid;
624 }
625
626
627 int eap_server_gpsk_register(void)
628 {
629         struct eap_method *eap;
630
631         eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
632                                       EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK");
633         if (eap == NULL)
634                 return -1;
635
636         eap->init = eap_gpsk_init;
637         eap->reset = eap_gpsk_reset;
638         eap->buildReq = eap_gpsk_buildReq;
639         eap->check = eap_gpsk_check;
640         eap->process = eap_gpsk_process;
641         eap->isDone = eap_gpsk_isDone;
642         eap->getKey = eap_gpsk_getKey;
643         eap->isSuccess = eap_gpsk_isSuccess;
644         eap->get_emsk = eap_gpsk_get_emsk;
645         eap->getSessionId = eap_gpsk_get_session_id;
646
647         return eap_server_method_register(eap);
648 }