Home | History | Annotate | Download | only in eap_peer
      1 /*
      2  * EAP peer method: EAP-GPSK (RFC 5433)
      3  * Copyright (c) 2006-2008, 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_peer/eap_i.h"
     14 #include "eap_common/eap_gpsk_common.h"
     15 
     16 struct eap_gpsk_data {
     17 	enum { GPSK_1, GPSK_3, SUCCESS, FAILURE } state;
     18 	u8 rand_server[EAP_GPSK_RAND_LEN];
     19 	u8 rand_peer[EAP_GPSK_RAND_LEN];
     20 	u8 msk[EAP_MSK_LEN];
     21 	u8 emsk[EAP_EMSK_LEN];
     22 	u8 sk[EAP_GPSK_MAX_SK_LEN];
     23 	size_t sk_len;
     24 	u8 pk[EAP_GPSK_MAX_PK_LEN];
     25 	size_t pk_len;
     26 	u8 session_id;
     27 	int session_id_set;
     28 	u8 *id_peer;
     29 	size_t id_peer_len;
     30 	u8 *id_server;
     31 	size_t id_server_len;
     32 	int vendor; /* CSuite/Specifier */
     33 	int specifier; /* CSuite/Specifier */
     34 	u8 *psk;
     35 	size_t psk_len;
     36 };
     37 
     38 
     39 static struct wpabuf * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data,
     40 					    u8 identifier,
     41 					    const u8 *csuite_list,
     42 					    size_t csuite_list_len);
     43 static struct wpabuf * eap_gpsk_send_gpsk_4(struct eap_gpsk_data *data,
     44 					    u8 identifier);
     45 
     46 
     47 #ifndef CONFIG_NO_STDOUT_DEBUG
     48 static const char * eap_gpsk_state_txt(int state)
     49 {
     50 	switch (state) {
     51 	case GPSK_1:
     52 		return "GPSK-1";
     53 	case GPSK_3:
     54 		return "GPSK-3";
     55 	case SUCCESS:
     56 		return "SUCCESS";
     57 	case FAILURE:
     58 		return "FAILURE";
     59 	default:
     60 		return "?";
     61 	}
     62 }
     63 #endif /* CONFIG_NO_STDOUT_DEBUG */
     64 
     65 
     66 static void eap_gpsk_state(struct eap_gpsk_data *data, int state)
     67 {
     68 	wpa_printf(MSG_DEBUG, "EAP-GPSK: %s -> %s",
     69 		   eap_gpsk_state_txt(data->state),
     70 		   eap_gpsk_state_txt(state));
     71 	data->state = state;
     72 }
     73 
     74 
     75 static void eap_gpsk_deinit(struct eap_sm *sm, void *priv);
     76 
     77 
     78 static void * eap_gpsk_init(struct eap_sm *sm)
     79 {
     80 	struct eap_gpsk_data *data;
     81 	const u8 *identity, *password;
     82 	size_t identity_len, password_len;
     83 
     84 	password = eap_get_config_password(sm, &password_len);
     85 	if (password == NULL) {
     86 		wpa_printf(MSG_INFO, "EAP-GPSK: No key (password) configured");
     87 		return NULL;
     88 	}
     89 
     90 	data = os_zalloc(sizeof(*data));
     91 	if (data == NULL)
     92 		return NULL;
     93 	data->state = GPSK_1;
     94 
     95 	identity = eap_get_config_identity(sm, &identity_len);
     96 	if (identity) {
     97 		data->id_peer = os_malloc(identity_len);
     98 		if (data->id_peer == NULL) {
     99 			eap_gpsk_deinit(sm, data);
    100 			return NULL;
    101 		}
    102 		os_memcpy(data->id_peer, identity, identity_len);
    103 		data->id_peer_len = identity_len;
    104 	}
    105 
    106 	data->psk = os_malloc(password_len);
    107 	if (data->psk == NULL) {
    108 		eap_gpsk_deinit(sm, data);
    109 		return NULL;
    110 	}
    111 	os_memcpy(data->psk, password, password_len);
    112 	data->psk_len = password_len;
    113 
    114 	return data;
    115 }
    116 
    117 
    118 static void eap_gpsk_deinit(struct eap_sm *sm, void *priv)
    119 {
    120 	struct eap_gpsk_data *data = priv;
    121 	os_free(data->id_server);
    122 	os_free(data->id_peer);
    123 	os_free(data->psk);
    124 	os_free(data);
    125 }
    126 
    127 
    128 static const u8 * eap_gpsk_process_id_server(struct eap_gpsk_data *data,
    129 					     const u8 *pos, const u8 *end)
    130 {
    131 	u16 alen;
    132 
    133 	if (end - pos < 2) {
    134 		wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short GPSK-1 packet");
    135 		return NULL;
    136 	}
    137 	alen = WPA_GET_BE16(pos);
    138 	pos += 2;
    139 	if (end - pos < alen) {
    140 		wpa_printf(MSG_DEBUG, "EAP-GPSK: ID_Server overflow");
    141 		return NULL;
    142 	}
    143 	os_free(data->id_server);
    144 	data->id_server = os_malloc(alen);
    145 	if (data->id_server == NULL) {
    146 		wpa_printf(MSG_DEBUG, "EAP-GPSK: No memory for ID_Server");
    147 		return NULL;
    148 	}
    149 	os_memcpy(data->id_server, pos, alen);
    150 	data->id_server_len = alen;
    151 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server",
    152 			  data->id_server, data->id_server_len);
    153 	pos += alen;
    154 
    155 	return pos;
    156 }
    157 
    158 
    159 static const u8 * eap_gpsk_process_rand_server(struct eap_gpsk_data *data,
    160 					       const u8 *pos, const u8 *end)
    161 {
    162 	if (pos == NULL)
    163 		return NULL;
    164 
    165 	if (end - pos < EAP_GPSK_RAND_LEN) {
    166 		wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server overflow");
    167 		return NULL;
    168 	}
    169 	os_memcpy(data->rand_server, pos, EAP_GPSK_RAND_LEN);
    170 	wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server",
    171 		    data->rand_server, EAP_GPSK_RAND_LEN);
    172 	pos += EAP_GPSK_RAND_LEN;
    173 
    174 	return pos;
    175 }
    176 
    177 
    178 static int eap_gpsk_select_csuite(struct eap_sm *sm,
    179 				  struct eap_gpsk_data *data,
    180 				  const u8 *csuite_list,
    181 				  size_t csuite_list_len)
    182 {
    183 	struct eap_gpsk_csuite *csuite;
    184 	int i, count;
    185 
    186 	count = csuite_list_len / sizeof(struct eap_gpsk_csuite);
    187 	data->vendor = EAP_GPSK_VENDOR_IETF;
    188 	data->specifier = EAP_GPSK_CIPHER_RESERVED;
    189 	csuite = (struct eap_gpsk_csuite *) csuite_list;
    190 	for (i = 0; i < count; i++) {
    191 		int vendor, specifier;
    192 		vendor = WPA_GET_BE32(csuite->vendor);
    193 		specifier = WPA_GET_BE16(csuite->specifier);
    194 		wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite[%d]: %d:%d",
    195 			   i, vendor, specifier);
    196 		if (data->vendor == EAP_GPSK_VENDOR_IETF &&
    197 		    data->specifier == EAP_GPSK_CIPHER_RESERVED &&
    198 		    eap_gpsk_supported_ciphersuite(vendor, specifier)) {
    199 			data->vendor = vendor;
    200 			data->specifier = specifier;
    201 		}
    202 		csuite++;
    203 	}
    204 	if (data->vendor == EAP_GPSK_VENDOR_IETF &&
    205 	    data->specifier == EAP_GPSK_CIPHER_RESERVED) {
    206 		wpa_msg(sm->msg_ctx, MSG_INFO, "EAP-GPSK: No supported "
    207 			"ciphersuite found");
    208 		return -1;
    209 	}
    210 	wpa_printf(MSG_DEBUG, "EAP-GPSK: Selected ciphersuite %d:%d",
    211 		   data->vendor, data->specifier);
    212 
    213 	return 0;
    214 }
    215 
    216 
    217 static const u8 * eap_gpsk_process_csuite_list(struct eap_sm *sm,
    218 					       struct eap_gpsk_data *data,
    219 					       const u8 **list,
    220 					       size_t *list_len,
    221 					       const u8 *pos, const u8 *end)
    222 {
    223 	if (pos == NULL)
    224 		return NULL;
    225 
    226 	if (end - pos < 2) {
    227 		wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short GPSK-1 packet");
    228 		return NULL;
    229 	}
    230 	*list_len = WPA_GET_BE16(pos);
    231 	pos += 2;
    232 	if (end - pos < (int) *list_len) {
    233 		wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_List overflow");
    234 		return NULL;
    235 	}
    236 	if (*list_len == 0 || (*list_len % sizeof(struct eap_gpsk_csuite))) {
    237 		wpa_printf(MSG_DEBUG, "EAP-GPSK: Invalid CSuite_List len %lu",
    238 			   (unsigned long) *list_len);
    239 		return NULL;
    240 	}
    241 	*list = pos;
    242 	pos += *list_len;
    243 
    244 	if (eap_gpsk_select_csuite(sm, data, *list, *list_len) < 0)
    245 		return NULL;
    246 
    247 	return pos;
    248 }
    249 
    250 
    251 static struct wpabuf * eap_gpsk_process_gpsk_1(struct eap_sm *sm,
    252 					       struct eap_gpsk_data *data,
    253 					       struct eap_method_ret *ret,
    254 					       const struct wpabuf *reqData,
    255 					       const u8 *payload,
    256 					       size_t payload_len)
    257 {
    258 	size_t csuite_list_len;
    259 	const u8 *csuite_list, *pos, *end;
    260 	struct wpabuf *resp;
    261 
    262 	if (data->state != GPSK_1) {
    263 		ret->ignore = TRUE;
    264 		return NULL;
    265 	}
    266 
    267 	wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Request/GPSK-1");
    268 
    269 	end = payload + payload_len;
    270 
    271 	pos = eap_gpsk_process_id_server(data, payload, end);
    272 	pos = eap_gpsk_process_rand_server(data, pos, end);
    273 	pos = eap_gpsk_process_csuite_list(sm, data, &csuite_list,
    274 					   &csuite_list_len, pos, end);
    275 	if (pos == NULL) {
    276 		eap_gpsk_state(data, FAILURE);
    277 		return NULL;
    278 	}
    279 
    280 	resp = eap_gpsk_send_gpsk_2(data, eap_get_id(reqData),
    281 				    csuite_list, csuite_list_len);
    282 	if (resp == NULL)
    283 		return NULL;
    284 
    285 	eap_gpsk_state(data, GPSK_3);
    286 
    287 	return resp;
    288 }
    289 
    290 
    291 static struct wpabuf * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data,
    292 					    u8 identifier,
    293 					    const u8 *csuite_list,
    294 					    size_t csuite_list_len)
    295 {
    296 	struct wpabuf *resp;
    297 	size_t len, miclen;
    298 	u8 *rpos, *start;
    299 	struct eap_gpsk_csuite *csuite;
    300 
    301 	wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-2");
    302 
    303 	miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
    304 	len = 1 + 2 + data->id_peer_len + 2 + data->id_server_len +
    305 		2 * EAP_GPSK_RAND_LEN + 2 + csuite_list_len +
    306 		sizeof(struct eap_gpsk_csuite) + 2 + miclen;
    307 
    308 	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len,
    309 			     EAP_CODE_RESPONSE, identifier);
    310 	if (resp == NULL)
    311 		return NULL;
    312 
    313 	wpabuf_put_u8(resp, EAP_GPSK_OPCODE_GPSK_2);
    314 	start = wpabuf_put(resp, 0);
    315 
    316 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer",
    317 			  data->id_peer, data->id_peer_len);
    318 	wpabuf_put_be16(resp, data->id_peer_len);
    319 	wpabuf_put_data(resp, data->id_peer, data->id_peer_len);
    320 
    321 	wpabuf_put_be16(resp, data->id_server_len);
    322 	wpabuf_put_data(resp, data->id_server, data->id_server_len);
    323 
    324 	if (random_get_bytes(data->rand_peer, EAP_GPSK_RAND_LEN)) {
    325 		wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to get random data "
    326 			   "for RAND_Peer");
    327 		eap_gpsk_state(data, FAILURE);
    328 		wpabuf_free(resp);
    329 		return NULL;
    330 	}
    331 	wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer",
    332 		    data->rand_peer, EAP_GPSK_RAND_LEN);
    333 	wpabuf_put_data(resp, data->rand_peer, EAP_GPSK_RAND_LEN);
    334 	wpabuf_put_data(resp, data->rand_server, EAP_GPSK_RAND_LEN);
    335 
    336 	wpabuf_put_be16(resp, csuite_list_len);
    337 	wpabuf_put_data(resp, csuite_list, csuite_list_len);
    338 
    339 	csuite = wpabuf_put(resp, sizeof(*csuite));
    340 	WPA_PUT_BE32(csuite->vendor, data->vendor);
    341 	WPA_PUT_BE16(csuite->specifier, data->specifier);
    342 
    343 	if (eap_gpsk_derive_keys(data->psk, data->psk_len,
    344 				 data->vendor, data->specifier,
    345 				 data->rand_peer, data->rand_server,
    346 				 data->id_peer, data->id_peer_len,
    347 				 data->id_server, data->id_server_len,
    348 				 data->msk, data->emsk,
    349 				 data->sk, &data->sk_len,
    350 				 data->pk, &data->pk_len) < 0) {
    351 		wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive keys");
    352 		eap_gpsk_state(data, FAILURE);
    353 		wpabuf_free(resp);
    354 		return NULL;
    355 	}
    356 
    357 	/* No PD_Payload_1 */
    358 	wpabuf_put_be16(resp, 0);
    359 
    360 	rpos = wpabuf_put(resp, miclen);
    361 	if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
    362 				 data->specifier, start, rpos - start, rpos) <
    363 	    0) {
    364 		eap_gpsk_state(data, FAILURE);
    365 		wpabuf_free(resp);
    366 		return NULL;
    367 	}
    368 
    369 	return resp;
    370 }
    371 
    372 
    373 static const u8 * eap_gpsk_validate_rand(struct eap_gpsk_data *data,
    374 					 const u8 *pos, const u8 *end)
    375 {
    376 	if (end - pos < EAP_GPSK_RAND_LEN) {
    377 		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
    378 			   "RAND_Peer");
    379 		return NULL;
    380 	}
    381 	if (os_memcmp(pos, data->rand_peer, EAP_GPSK_RAND_LEN) != 0) {
    382 		wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-2 and "
    383 			   "GPSK-3 did not match");
    384 		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-2",
    385 			    data->rand_peer, EAP_GPSK_RAND_LEN);
    386 		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-3",
    387 			    pos, EAP_GPSK_RAND_LEN);
    388 		return NULL;
    389 	}
    390 	pos += EAP_GPSK_RAND_LEN;
    391 
    392 	if (end - pos < EAP_GPSK_RAND_LEN) {
    393 		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
    394 			   "RAND_Server");
    395 		return NULL;
    396 	}
    397 	if (os_memcmp(pos, data->rand_server, EAP_GPSK_RAND_LEN) != 0) {
    398 		wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1 and "
    399 			   "GPSK-3 did not match");
    400 		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1",
    401 			    data->rand_server, EAP_GPSK_RAND_LEN);
    402 		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-3",
    403 			    pos, EAP_GPSK_RAND_LEN);
    404 		return NULL;
    405 	}
    406 	pos += EAP_GPSK_RAND_LEN;
    407 
    408 	return pos;
    409 }
    410 
    411 
    412 static const u8 * eap_gpsk_validate_id_server(struct eap_gpsk_data *data,
    413 					      const u8 *pos, const u8 *end)
    414 {
    415 	size_t len;
    416 
    417 	if (pos == NULL)
    418 		return NULL;
    419 
    420 	if (end - pos < (int) 2) {
    421 		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
    422 			   "length(ID_Server)");
    423 		return NULL;
    424 	}
    425 
    426 	len = WPA_GET_BE16(pos);
    427 	pos += 2;
    428 
    429 	if (end - pos < (int) len) {
    430 		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
    431 			   "ID_Server");
    432 		return NULL;
    433 	}
    434 
    435 	if (len != data->id_server_len ||
    436 	    os_memcmp(pos, data->id_server, len) != 0) {
    437 		wpa_printf(MSG_INFO, "EAP-GPSK: ID_Server did not match with "
    438 			   "the one used in GPSK-1");
    439 		wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-1",
    440 				  data->id_server, data->id_server_len);
    441 		wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-3",
    442 				  pos, len);
    443 		return NULL;
    444 	}
    445 
    446 	pos += len;
    447 
    448 	return pos;
    449 }
    450 
    451 
    452 static const u8 * eap_gpsk_validate_csuite(struct eap_gpsk_data *data,
    453 					   const u8 *pos, const u8 *end)
    454 {
    455 	int vendor, specifier;
    456 	const struct eap_gpsk_csuite *csuite;
    457 
    458 	if (pos == NULL)
    459 		return NULL;
    460 
    461 	if (end - pos < (int) sizeof(*csuite)) {
    462 		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
    463 			   "CSuite_Sel");
    464 		return NULL;
    465 	}
    466 	csuite = (const struct eap_gpsk_csuite *) pos;
    467 	vendor = WPA_GET_BE32(csuite->vendor);
    468 	specifier = WPA_GET_BE16(csuite->specifier);
    469 	pos += sizeof(*csuite);
    470 	if (vendor != data->vendor || specifier != data->specifier) {
    471 		wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel (%d:%d) does not "
    472 			   "match with the one sent in GPSK-2 (%d:%d)",
    473 			   vendor, specifier, data->vendor, data->specifier);
    474 		return NULL;
    475 	}
    476 
    477 	return pos;
    478 }
    479 
    480 
    481 static const u8 * eap_gpsk_validate_pd_payload_2(struct eap_gpsk_data *data,
    482 						 const u8 *pos, const u8 *end)
    483 {
    484 	u16 alen;
    485 
    486 	if (pos == NULL)
    487 		return NULL;
    488 
    489 	if (end - pos < 2) {
    490 		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
    491 			   "PD_Payload_2 length");
    492 		return NULL;
    493 	}
    494 	alen = WPA_GET_BE16(pos);
    495 	pos += 2;
    496 	if (end - pos < alen) {
    497 		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for "
    498 			   "%d-octet PD_Payload_2", alen);
    499 		return NULL;
    500 	}
    501 	wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_2", pos, alen);
    502 	pos += alen;
    503 
    504 	return pos;
    505 }
    506 
    507 
    508 static const u8 * eap_gpsk_validate_gpsk_3_mic(struct eap_gpsk_data *data,
    509 					       const u8 *payload,
    510 					       const u8 *pos, const u8 *end)
    511 {
    512 	size_t miclen;
    513 	u8 mic[EAP_GPSK_MAX_MIC_LEN];
    514 
    515 	if (pos == NULL)
    516 		return NULL;
    517 
    518 	miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
    519 	if (end - pos < (int) miclen) {
    520 		wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC "
    521 			   "(left=%lu miclen=%lu)",
    522 			   (unsigned long) (end - pos),
    523 			   (unsigned long) miclen);
    524 		return NULL;
    525 	}
    526 	if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
    527 				 data->specifier, payload, pos - payload, mic)
    528 	    < 0) {
    529 		wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC");
    530 		return NULL;
    531 	}
    532 	if (os_memcmp(mic, pos, miclen) != 0) {
    533 		wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-3");
    534 		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen);
    535 		wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen);
    536 		return NULL;
    537 	}
    538 	pos += miclen;
    539 
    540 	return pos;
    541 }
    542 
    543 
    544 static struct wpabuf * eap_gpsk_process_gpsk_3(struct eap_sm *sm,
    545 					       struct eap_gpsk_data *data,
    546 					       struct eap_method_ret *ret,
    547 					       const struct wpabuf *reqData,
    548 					       const u8 *payload,
    549 					       size_t payload_len)
    550 {
    551 	struct wpabuf *resp;
    552 	const u8 *pos, *end;
    553 
    554 	if (data->state != GPSK_3) {
    555 		ret->ignore = TRUE;
    556 		return NULL;
    557 	}
    558 
    559 	wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Request/GPSK-3");
    560 
    561 	end = payload + payload_len;
    562 
    563 	pos = eap_gpsk_validate_rand(data, payload, end);
    564 	pos = eap_gpsk_validate_id_server(data, pos, end);
    565 	pos = eap_gpsk_validate_csuite(data, pos, end);
    566 	pos = eap_gpsk_validate_pd_payload_2(data, pos, end);
    567 	pos = eap_gpsk_validate_gpsk_3_mic(data, payload, pos, end);
    568 
    569 	if (pos == NULL) {
    570 		eap_gpsk_state(data, FAILURE);
    571 		return NULL;
    572 	}
    573 	if (pos != end) {
    574 		wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra "
    575 			   "data in the end of GPSK-2",
    576 			   (unsigned long) (end - pos));
    577 	}
    578 
    579 	resp = eap_gpsk_send_gpsk_4(data, eap_get_id(reqData));
    580 	if (resp == NULL)
    581 		return NULL;
    582 
    583 	eap_gpsk_state(data, SUCCESS);
    584 	ret->methodState = METHOD_DONE;
    585 	ret->decision = DECISION_UNCOND_SUCC;
    586 
    587 	return resp;
    588 }
    589 
    590 
    591 static struct wpabuf * eap_gpsk_send_gpsk_4(struct eap_gpsk_data *data,
    592 					    u8 identifier)
    593 {
    594 	struct wpabuf *resp;
    595 	u8 *rpos, *start;
    596 	size_t mlen;
    597 
    598 	wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-4");
    599 
    600 	mlen = eap_gpsk_mic_len(data->vendor, data->specifier);
    601 
    602 	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, 1 + 2 + mlen,
    603 			     EAP_CODE_RESPONSE, identifier);
    604 	if (resp == NULL)
    605 		return NULL;
    606 
    607 	wpabuf_put_u8(resp, EAP_GPSK_OPCODE_GPSK_4);
    608 	start = wpabuf_put(resp, 0);
    609 
    610 	/* No PD_Payload_3 */
    611 	wpabuf_put_be16(resp, 0);
    612 
    613 	rpos = wpabuf_put(resp, mlen);
    614 	if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
    615 				 data->specifier, start, rpos - start, rpos) <
    616 	    0) {
    617 		eap_gpsk_state(data, FAILURE);
    618 		wpabuf_free(resp);
    619 		return NULL;
    620 	}
    621 
    622 	return resp;
    623 }
    624 
    625 
    626 static struct wpabuf * eap_gpsk_process(struct eap_sm *sm, void *priv,
    627 					struct eap_method_ret *ret,
    628 					const struct wpabuf *reqData)
    629 {
    630 	struct eap_gpsk_data *data = priv;
    631 	struct wpabuf *resp;
    632 	const u8 *pos;
    633 	size_t len;
    634 
    635 	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, reqData, &len);
    636 	if (pos == NULL || len < 1) {
    637 		ret->ignore = TRUE;
    638 		return NULL;
    639 	}
    640 
    641 	wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode %d", *pos);
    642 
    643 	ret->ignore = FALSE;
    644 	ret->methodState = METHOD_MAY_CONT;
    645 	ret->decision = DECISION_FAIL;
    646 	ret->allowNotifications = FALSE;
    647 
    648 	switch (*pos) {
    649 	case EAP_GPSK_OPCODE_GPSK_1:
    650 		resp = eap_gpsk_process_gpsk_1(sm, data, ret, reqData,
    651 					       pos + 1, len - 1);
    652 		break;
    653 	case EAP_GPSK_OPCODE_GPSK_3:
    654 		resp = eap_gpsk_process_gpsk_3(sm, data, ret, reqData,
    655 					       pos + 1, len - 1);
    656 		break;
    657 	default:
    658 		wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignoring message with "
    659 			   "unknown opcode %d", *pos);
    660 		ret->ignore = TRUE;
    661 		return NULL;
    662 	}
    663 
    664 	return resp;
    665 }
    666 
    667 
    668 static Boolean eap_gpsk_isKeyAvailable(struct eap_sm *sm, void *priv)
    669 {
    670 	struct eap_gpsk_data *data = priv;
    671 	return data->state == SUCCESS;
    672 }
    673 
    674 
    675 static u8 * eap_gpsk_getKey(struct eap_sm *sm, void *priv, size_t *len)
    676 {
    677 	struct eap_gpsk_data *data = priv;
    678 	u8 *key;
    679 
    680 	if (data->state != SUCCESS)
    681 		return NULL;
    682 
    683 	key = os_malloc(EAP_MSK_LEN);
    684 	if (key == NULL)
    685 		return NULL;
    686 	os_memcpy(key, data->msk, EAP_MSK_LEN);
    687 	*len = EAP_MSK_LEN;
    688 
    689 	return key;
    690 }
    691 
    692 
    693 static u8 * eap_gpsk_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
    694 {
    695 	struct eap_gpsk_data *data = priv;
    696 	u8 *key;
    697 
    698 	if (data->state != SUCCESS)
    699 		return NULL;
    700 
    701 	key = os_malloc(EAP_EMSK_LEN);
    702 	if (key == NULL)
    703 		return NULL;
    704 	os_memcpy(key, data->emsk, EAP_EMSK_LEN);
    705 	*len = EAP_EMSK_LEN;
    706 
    707 	return key;
    708 }
    709 
    710 
    711 int eap_peer_gpsk_register(void)
    712 {
    713 	struct eap_method *eap;
    714 	int ret;
    715 
    716 	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
    717 				    EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK");
    718 	if (eap == NULL)
    719 		return -1;
    720 
    721 	eap->init = eap_gpsk_init;
    722 	eap->deinit = eap_gpsk_deinit;
    723 	eap->process = eap_gpsk_process;
    724 	eap->isKeyAvailable = eap_gpsk_isKeyAvailable;
    725 	eap->getKey = eap_gpsk_getKey;
    726 	eap->get_emsk = eap_gpsk_get_emsk;
    727 
    728 	ret = eap_peer_method_register(eap);
    729 	if (ret)
    730 		eap_peer_method_free(eap);
    731 	return ret;
    732 }
    733