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