Updated through tag hostap_2_5 from git://w1.fi/hostap.git
[mech_eap.git] / libeap / 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                 os_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_malloc(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         os_memcpy(data->id_peer, pos, alen);
279         data->id_peer_len = alen;
280         wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer",
281                           data->id_peer, data->id_peer_len);
282         pos += alen;
283
284         if (end - pos < 2) {
285                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
286                            "ID_Server length");
287                 eap_gpsk_state(data, FAILURE);
288                 return;
289         }
290         alen = WPA_GET_BE16(pos);
291         pos += 2;
292         if (end - pos < alen) {
293                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
294                            "ID_Server");
295                 eap_gpsk_state(data, FAILURE);
296                 return;
297         }
298         if (alen != sm->server_id_len ||
299             os_memcmp(pos, sm->server_id, alen) != 0) {
300                 wpa_printf(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-1 and "
301                            "GPSK-2 did not match");
302                 eap_gpsk_state(data, FAILURE);
303                 return;
304         }
305         pos += alen;
306
307         if (end - pos < EAP_GPSK_RAND_LEN) {
308                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
309                            "RAND_Peer");
310                 eap_gpsk_state(data, FAILURE);
311                 return;
312         }
313         os_memcpy(data->rand_peer, pos, EAP_GPSK_RAND_LEN);
314         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer",
315                     data->rand_peer, EAP_GPSK_RAND_LEN);
316         pos += EAP_GPSK_RAND_LEN;
317
318         if (end - pos < EAP_GPSK_RAND_LEN) {
319                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
320                            "RAND_Server");
321                 eap_gpsk_state(data, FAILURE);
322                 return;
323         }
324         if (os_memcmp(data->rand_server, pos, EAP_GPSK_RAND_LEN) != 0) {
325                 wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1 and "
326                            "GPSK-2 did not match");
327                 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1",
328                             data->rand_server, EAP_GPSK_RAND_LEN);
329                 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-2",
330                             pos, EAP_GPSK_RAND_LEN);
331                 eap_gpsk_state(data, FAILURE);
332                 return;
333         }
334         pos += EAP_GPSK_RAND_LEN;
335
336         if (end - pos < 2) {
337                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
338                            "CSuite_List length");
339                 eap_gpsk_state(data, FAILURE);
340                 return;
341         }
342         alen = WPA_GET_BE16(pos);
343         pos += 2;
344         if (end - pos < alen) {
345                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
346                            "CSuite_List");
347                 eap_gpsk_state(data, FAILURE);
348                 return;
349         }
350         if (alen != data->csuite_count * sizeof(struct eap_gpsk_csuite) ||
351             os_memcmp(pos, data->csuite_list, alen) != 0) {
352                 wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_List in GPSK-1 and "
353                            "GPSK-2 did not match");
354                 eap_gpsk_state(data, FAILURE);
355                 return;
356         }
357         pos += alen;
358
359         if (end - pos < (int) sizeof(*csuite)) {
360                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
361                            "CSuite_Sel");
362                 eap_gpsk_state(data, FAILURE);
363                 return;
364         }
365         csuite = (const struct eap_gpsk_csuite *) pos;
366         for (i = 0; i < data->csuite_count; i++) {
367                 if (os_memcmp(csuite, &data->csuite_list[i], sizeof(*csuite))
368                     == 0)
369                         break;
370         }
371         if (i == data->csuite_count) {
372                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Peer selected unsupported "
373                            "ciphersuite %d:%d",
374                            WPA_GET_BE32(csuite->vendor),
375                            WPA_GET_BE16(csuite->specifier));
376                 eap_gpsk_state(data, FAILURE);
377                 return;
378         }
379         data->vendor = WPA_GET_BE32(csuite->vendor);
380         data->specifier = WPA_GET_BE16(csuite->specifier);
381         wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel %d:%d",
382                    data->vendor, data->specifier);
383         pos += sizeof(*csuite); 
384
385         if (end - pos < 2) {
386                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
387                            "PD_Payload_1 length");
388                 eap_gpsk_state(data, FAILURE);
389                 return;
390         }
391         alen = WPA_GET_BE16(pos);
392         pos += 2;
393         if (end - pos < alen) {
394                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
395                            "PD_Payload_1");
396                 eap_gpsk_state(data, FAILURE);
397                 return;
398         }
399         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_1", pos, alen);
400         pos += alen;
401
402         if (sm->user == NULL || sm->user->password == NULL) {
403                 wpa_printf(MSG_INFO, "EAP-GPSK: No PSK/password configured "
404                            "for the user");
405                 eap_gpsk_state(data, FAILURE);
406                 return;
407         }
408
409         if (eap_gpsk_derive_keys(sm->user->password, sm->user->password_len,
410                                  data->vendor, data->specifier,
411                                  data->rand_peer, data->rand_server,
412                                  data->id_peer, data->id_peer_len,
413                                  sm->server_id, sm->server_id_len,
414                                  data->msk, data->emsk,
415                                  data->sk, &data->sk_len,
416                                  data->pk, &data->pk_len) < 0) {
417                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive keys");
418                 eap_gpsk_state(data, FAILURE);
419                 return;
420         }
421
422         if (eap_gpsk_derive_session_id(sm->user->password,
423                                        sm->user->password_len,
424                                        data->vendor, data->specifier,
425                                        data->rand_peer, data->rand_server,
426                                        data->id_peer, data->id_peer_len,
427                                        sm->server_id, sm->server_id_len,
428                                        EAP_TYPE_GPSK,
429                                        data->session_id, &data->id_len) < 0) {
430                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive Session-Id");
431                 eap_gpsk_state(data, FAILURE);
432                 return;
433         }
434         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Derived Session-Id",
435                     data->session_id, data->id_len);
436
437         miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
438         if (end - pos < (int) miclen) {
439                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC "
440                            "(left=%lu miclen=%lu)",
441                            (unsigned long) (end - pos),
442                            (unsigned long) miclen);
443                 eap_gpsk_state(data, FAILURE);
444                 return;
445         }
446         if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
447                                  data->specifier, payload, pos - payload, mic)
448             < 0) {
449                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC");
450                 eap_gpsk_state(data, FAILURE);
451                 return;
452         }
453         if (os_memcmp_const(mic, pos, miclen) != 0) {
454                 wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-2");
455                 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen);
456                 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen);
457                 eap_gpsk_state(data, FAILURE);
458                 return;
459         }
460         pos += miclen;
461
462         if (pos != end) {
463                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra "
464                            "data in the end of GPSK-2",
465                            (unsigned long) (end - pos));
466         }
467
468         eap_gpsk_state(data, GPSK_3);
469 }
470
471
472 static void eap_gpsk_process_gpsk_4(struct eap_sm *sm,
473                                     struct eap_gpsk_data *data,
474                                     const u8 *payload, size_t payloadlen)
475 {
476         const u8 *pos, *end;
477         u16 alen;
478         size_t miclen;
479         u8 mic[EAP_GPSK_MAX_MIC_LEN];
480
481         if (data->state != GPSK_3)
482                 return;
483
484         wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Response/GPSK-4");
485
486         pos = payload;
487         end = payload + payloadlen;
488
489         if (end - pos < 2) {
490                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
491                            "PD_Payload_1 length");
492                 eap_gpsk_state(data, FAILURE);
493                 return;
494         }
495         alen = WPA_GET_BE16(pos);
496         pos += 2;
497         if (end - pos < alen) {
498                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for "
499                            "PD_Payload_1");
500                 eap_gpsk_state(data, FAILURE);
501                 return;
502         }
503         wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_1", pos, alen);
504         pos += alen;
505
506         miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
507         if (end - pos < (int) miclen) {
508                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC "
509                            "(left=%lu miclen=%lu)",
510                            (unsigned long) (end - pos),
511                            (unsigned long) miclen);
512                 eap_gpsk_state(data, FAILURE);
513                 return;
514         }
515         if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
516                                  data->specifier, payload, pos - payload, mic)
517             < 0) {
518                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC");
519                 eap_gpsk_state(data, FAILURE);
520                 return;
521         }
522         if (os_memcmp_const(mic, pos, miclen) != 0) {
523                 wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-4");
524                 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen);
525                 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen);
526                 eap_gpsk_state(data, FAILURE);
527                 return;
528         }
529         pos += miclen;
530
531         if (pos != end) {
532                 wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra "
533                            "data in the end of GPSK-4",
534                            (unsigned long) (end - pos));
535         }
536
537         eap_gpsk_state(data, SUCCESS);
538 }
539
540
541 static void eap_gpsk_process(struct eap_sm *sm, void *priv,
542                              struct wpabuf *respData)
543 {
544         struct eap_gpsk_data *data = priv;
545         const u8 *pos;
546         size_t len;
547
548         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respData, &len);
549         if (pos == NULL || len < 1)
550                 return;
551
552         switch (*pos) {
553         case EAP_GPSK_OPCODE_GPSK_2:
554                 eap_gpsk_process_gpsk_2(sm, data, pos + 1, len - 1);
555                 break;
556         case EAP_GPSK_OPCODE_GPSK_4:
557                 eap_gpsk_process_gpsk_4(sm, data, pos + 1, len - 1);
558                 break;
559         }
560 }
561
562
563 static Boolean eap_gpsk_isDone(struct eap_sm *sm, void *priv)
564 {
565         struct eap_gpsk_data *data = priv;
566         return data->state == SUCCESS || data->state == FAILURE;
567 }
568
569
570 static u8 * eap_gpsk_getKey(struct eap_sm *sm, void *priv, size_t *len)
571 {
572         struct eap_gpsk_data *data = priv;
573         u8 *key;
574
575         if (data->state != SUCCESS)
576                 return NULL;
577
578         key = os_malloc(EAP_MSK_LEN);
579         if (key == NULL)
580                 return NULL;
581         os_memcpy(key, data->msk, EAP_MSK_LEN);
582         *len = EAP_MSK_LEN;
583
584         return key;
585 }
586
587
588 static u8 * eap_gpsk_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
589 {
590         struct eap_gpsk_data *data = priv;
591         u8 *key;
592
593         if (data->state != SUCCESS)
594                 return NULL;
595
596         key = os_malloc(EAP_EMSK_LEN);
597         if (key == NULL)
598                 return NULL;
599         os_memcpy(key, data->emsk, EAP_EMSK_LEN);
600         *len = EAP_EMSK_LEN;
601
602         return key;
603 }
604
605
606 static Boolean eap_gpsk_isSuccess(struct eap_sm *sm, void *priv)
607 {
608         struct eap_gpsk_data *data = priv;
609         return data->state == SUCCESS;
610 }
611
612
613 static u8 * eap_gpsk_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
614 {
615         struct eap_gpsk_data *data = priv;
616         u8 *sid;
617
618         if (data->state != SUCCESS)
619                 return NULL;
620
621         sid = os_malloc(data->id_len);
622         if (sid == NULL)
623                 return NULL;
624         os_memcpy(sid, data->session_id, data->id_len);
625         *len = data->id_len;
626
627         return sid;
628 }
629
630
631 int eap_server_gpsk_register(void)
632 {
633         struct eap_method *eap;
634         int ret;
635
636         eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
637                                       EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK");
638         if (eap == NULL)
639                 return -1;
640
641         eap->init = eap_gpsk_init;
642         eap->reset = eap_gpsk_reset;
643         eap->buildReq = eap_gpsk_buildReq;
644         eap->check = eap_gpsk_check;
645         eap->process = eap_gpsk_process;
646         eap->isDone = eap_gpsk_isDone;
647         eap->getKey = eap_gpsk_getKey;
648         eap->isSuccess = eap_gpsk_isSuccess;
649         eap->get_emsk = eap_gpsk_get_emsk;
650         eap->getSessionId = eap_gpsk_get_session_id;
651
652         ret = eap_server_method_register(eap);
653         if (ret)
654                 eap_server_method_free(eap);
655         return ret;
656 }