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 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 	bin_clear_free(data, sizeof(*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_const(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_const(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