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