Home | History | Annotate | Download | only in eap_server
      1 /*
      2  * hostapd / EAP-pwd (RFC 5931) server
      3  * Copyright (c) 2010, Dan Harkins <dharkins (at) lounge.org>
      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/sha256.h"
     13 #include "crypto/ms_funcs.h"
     14 #include "eap_server/eap_i.h"
     15 #include "eap_common/eap_pwd_common.h"
     16 
     17 
     18 struct eap_pwd_data {
     19 	enum {
     20 		PWD_ID_Req, PWD_Commit_Req, PWD_Confirm_Req, SUCCESS, FAILURE
     21 	} state;
     22 	u8 *id_peer;
     23 	size_t id_peer_len;
     24 	u8 *id_server;
     25 	size_t id_server_len;
     26 	u8 *password;
     27 	size_t password_len;
     28 	int password_hash;
     29 	u32 token;
     30 	u16 group_num;
     31 	EAP_PWD_group *grp;
     32 
     33 	struct wpabuf *inbuf;
     34 	size_t in_frag_pos;
     35 	struct wpabuf *outbuf;
     36 	size_t out_frag_pos;
     37 	size_t mtu;
     38 
     39 	BIGNUM *k;
     40 	BIGNUM *private_value;
     41 	BIGNUM *peer_scalar;
     42 	BIGNUM *my_scalar;
     43 	EC_POINT *my_element;
     44 	EC_POINT *peer_element;
     45 
     46 	u8 my_confirm[SHA256_MAC_LEN];
     47 
     48 	u8 msk[EAP_MSK_LEN];
     49 	u8 emsk[EAP_EMSK_LEN];
     50 	u8 session_id[1 + SHA256_MAC_LEN];
     51 
     52 	BN_CTX *bnctx;
     53 };
     54 
     55 
     56 static const char * eap_pwd_state_txt(int state)
     57 {
     58 	switch (state) {
     59         case PWD_ID_Req:
     60 		return "PWD-ID-Req";
     61         case PWD_Commit_Req:
     62 		return "PWD-Commit-Req";
     63         case PWD_Confirm_Req:
     64 		return "PWD-Confirm-Req";
     65         case SUCCESS:
     66 		return "SUCCESS";
     67         case FAILURE:
     68 		return "FAILURE";
     69         default:
     70 		return "PWD-Unk";
     71 	}
     72 }
     73 
     74 
     75 static void eap_pwd_state(struct eap_pwd_data *data, int state)
     76 {
     77 	wpa_printf(MSG_DEBUG, "EAP-pwd: %s -> %s",
     78 		   eap_pwd_state_txt(data->state), eap_pwd_state_txt(state));
     79 	data->state = state;
     80 }
     81 
     82 
     83 static void * eap_pwd_init(struct eap_sm *sm)
     84 {
     85 	struct eap_pwd_data *data;
     86 
     87 	if (sm->user == NULL || sm->user->password == NULL ||
     88 	    sm->user->password_len == 0) {
     89 		wpa_printf(MSG_INFO, "EAP-PWD (server): Password is not "
     90 			   "configured");
     91 		return NULL;
     92 	}
     93 
     94 	data = os_zalloc(sizeof(*data));
     95 	if (data == NULL)
     96 		return NULL;
     97 
     98 	data->group_num = sm->pwd_group;
     99 	wpa_printf(MSG_DEBUG, "EAP-pwd: Selected group number %d",
    100 		   data->group_num);
    101 	data->state = PWD_ID_Req;
    102 
    103 	data->id_server = (u8 *) os_strdup("server");
    104 	if (data->id_server)
    105 		data->id_server_len = os_strlen((char *) data->id_server);
    106 
    107 	data->password = os_malloc(sm->user->password_len);
    108 	if (data->password == NULL) {
    109 		wpa_printf(MSG_INFO, "EAP-PWD: Memory allocation password "
    110 			   "fail");
    111 		bin_clear_free(data->id_server, data->id_server_len);
    112 		os_free(data);
    113 		return NULL;
    114 	}
    115 	data->password_len = sm->user->password_len;
    116 	os_memcpy(data->password, sm->user->password, data->password_len);
    117 	data->password_hash = sm->user->password_hash;
    118 
    119 	data->bnctx = BN_CTX_new();
    120 	if (data->bnctx == NULL) {
    121 		wpa_printf(MSG_INFO, "EAP-PWD: bn context allocation fail");
    122 		bin_clear_free(data->password, data->password_len);
    123 		bin_clear_free(data->id_server, data->id_server_len);
    124 		os_free(data);
    125 		return NULL;
    126 	}
    127 
    128 	data->in_frag_pos = data->out_frag_pos = 0;
    129 	data->inbuf = data->outbuf = NULL;
    130 	/* use default MTU from RFC 5931 if not configured otherwise */
    131 	data->mtu = sm->fragment_size > 0 ? sm->fragment_size : 1020;
    132 
    133 	return data;
    134 }
    135 
    136 
    137 static void eap_pwd_reset(struct eap_sm *sm, void *priv)
    138 {
    139 	struct eap_pwd_data *data = priv;
    140 
    141 	BN_clear_free(data->private_value);
    142 	BN_clear_free(data->peer_scalar);
    143 	BN_clear_free(data->my_scalar);
    144 	BN_clear_free(data->k);
    145 	BN_CTX_free(data->bnctx);
    146 	EC_POINT_clear_free(data->my_element);
    147 	EC_POINT_clear_free(data->peer_element);
    148 	bin_clear_free(data->id_peer, data->id_peer_len);
    149 	bin_clear_free(data->id_server, data->id_server_len);
    150 	bin_clear_free(data->password, data->password_len);
    151 	if (data->grp) {
    152 		EC_GROUP_free(data->grp->group);
    153 		EC_POINT_clear_free(data->grp->pwe);
    154 		BN_clear_free(data->grp->order);
    155 		BN_clear_free(data->grp->prime);
    156 		os_free(data->grp);
    157 	}
    158 	wpabuf_free(data->inbuf);
    159 	wpabuf_free(data->outbuf);
    160 	bin_clear_free(data, sizeof(*data));
    161 }
    162 
    163 
    164 static void eap_pwd_build_id_req(struct eap_sm *sm, struct eap_pwd_data *data,
    165 				 u8 id)
    166 {
    167 	wpa_printf(MSG_DEBUG, "EAP-pwd: ID/Request");
    168 	/*
    169 	 * if we're fragmenting then we already have an id request, just return
    170 	 */
    171 	if (data->out_frag_pos)
    172 		return;
    173 
    174 	data->outbuf = wpabuf_alloc(sizeof(struct eap_pwd_id) +
    175 				    data->id_server_len);
    176 	if (data->outbuf == NULL) {
    177 		eap_pwd_state(data, FAILURE);
    178 		return;
    179 	}
    180 
    181 	/* an lfsr is good enough to generate unpredictable tokens */
    182 	data->token = os_random();
    183 	wpabuf_put_be16(data->outbuf, data->group_num);
    184 	wpabuf_put_u8(data->outbuf, EAP_PWD_DEFAULT_RAND_FUNC);
    185 	wpabuf_put_u8(data->outbuf, EAP_PWD_DEFAULT_PRF);
    186 	wpabuf_put_data(data->outbuf, &data->token, sizeof(data->token));
    187 	wpabuf_put_u8(data->outbuf, data->password_hash ? EAP_PWD_PREP_MS :
    188 		      EAP_PWD_PREP_NONE);
    189 	wpabuf_put_data(data->outbuf, data->id_server, data->id_server_len);
    190 }
    191 
    192 
    193 static void eap_pwd_build_commit_req(struct eap_sm *sm,
    194 				     struct eap_pwd_data *data, u8 id)
    195 {
    196 	BIGNUM *mask = NULL, *x = NULL, *y = NULL;
    197 	u8 *scalar = NULL, *element = NULL;
    198 	u16 offset;
    199 
    200 	wpa_printf(MSG_DEBUG, "EAP-pwd: Commit/Request");
    201 	/*
    202 	 * if we're fragmenting then we already have an commit request, just
    203 	 * return
    204 	 */
    205 	if (data->out_frag_pos)
    206 		return;
    207 
    208 	if (((data->private_value = BN_new()) == NULL) ||
    209 	    ((data->my_element = EC_POINT_new(data->grp->group)) == NULL) ||
    210 	    ((data->my_scalar = BN_new()) == NULL) ||
    211 	    ((mask = BN_new()) == NULL)) {
    212 		wpa_printf(MSG_INFO, "EAP-PWD (server): scalar allocation "
    213 			   "fail");
    214 		goto fin;
    215 	}
    216 
    217 	if (BN_rand_range(data->private_value, data->grp->order) != 1 ||
    218 	    BN_rand_range(mask, data->grp->order) != 1 ||
    219 	    BN_add(data->my_scalar, data->private_value, mask) != 1 ||
    220 	    BN_mod(data->my_scalar, data->my_scalar, data->grp->order,
    221 		   data->bnctx) != 1) {
    222 		wpa_printf(MSG_INFO,
    223 			   "EAP-pwd (server): unable to get randomness");
    224 		goto fin;
    225 	}
    226 
    227 	if (!EC_POINT_mul(data->grp->group, data->my_element, NULL,
    228 			  data->grp->pwe, mask, data->bnctx)) {
    229 		wpa_printf(MSG_INFO, "EAP-PWD (server): element allocation "
    230 			   "fail");
    231 		eap_pwd_state(data, FAILURE);
    232 		goto fin;
    233 	}
    234 
    235 	if (!EC_POINT_invert(data->grp->group, data->my_element, data->bnctx))
    236 	{
    237 		wpa_printf(MSG_INFO, "EAP-PWD (server): element inversion "
    238 			   "fail");
    239 		goto fin;
    240 	}
    241 	BN_clear_free(mask);
    242 
    243 	if (((x = BN_new()) == NULL) ||
    244 	    ((y = BN_new()) == NULL)) {
    245 		wpa_printf(MSG_INFO, "EAP-PWD (server): point allocation "
    246 			   "fail");
    247 		goto fin;
    248 	}
    249 	if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
    250 						 data->my_element, x, y,
    251 						 data->bnctx)) {
    252 		wpa_printf(MSG_INFO, "EAP-PWD (server): point assignment "
    253 			   "fail");
    254 		goto fin;
    255 	}
    256 
    257 	if (((scalar = os_malloc(BN_num_bytes(data->grp->order))) == NULL) ||
    258 	    ((element = os_malloc(BN_num_bytes(data->grp->prime) * 2)) ==
    259 	     NULL)) {
    260 		wpa_printf(MSG_INFO, "EAP-PWD (server): data allocation fail");
    261 		goto fin;
    262 	}
    263 
    264 	/*
    265 	 * bignums occupy as little memory as possible so one that is
    266 	 * sufficiently smaller than the prime or order might need pre-pending
    267 	 * with zeros.
    268 	 */
    269 	os_memset(scalar, 0, BN_num_bytes(data->grp->order));
    270 	os_memset(element, 0, BN_num_bytes(data->grp->prime) * 2);
    271 	offset = BN_num_bytes(data->grp->order) -
    272 		BN_num_bytes(data->my_scalar);
    273 	BN_bn2bin(data->my_scalar, scalar + offset);
    274 
    275 	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
    276 	BN_bn2bin(x, element + offset);
    277 	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
    278 	BN_bn2bin(y, element + BN_num_bytes(data->grp->prime) + offset);
    279 
    280 	data->outbuf = wpabuf_alloc(2 * BN_num_bytes(data->grp->prime) +
    281 				    BN_num_bytes(data->grp->order));
    282 	if (data->outbuf == NULL)
    283 		goto fin;
    284 
    285 	/* We send the element as (x,y) followed by the scalar */
    286 	wpabuf_put_data(data->outbuf, element,
    287 			2 * BN_num_bytes(data->grp->prime));
    288 	wpabuf_put_data(data->outbuf, scalar, BN_num_bytes(data->grp->order));
    289 
    290 fin:
    291 	os_free(scalar);
    292 	os_free(element);
    293 	BN_clear_free(x);
    294 	BN_clear_free(y);
    295 	if (data->outbuf == NULL)
    296 		eap_pwd_state(data, FAILURE);
    297 }
    298 
    299 
    300 static void eap_pwd_build_confirm_req(struct eap_sm *sm,
    301 				      struct eap_pwd_data *data, u8 id)
    302 {
    303 	BIGNUM *x = NULL, *y = NULL;
    304 	struct crypto_hash *hash;
    305 	u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr;
    306 	u16 grp;
    307 	int offset;
    308 
    309 	wpa_printf(MSG_DEBUG, "EAP-pwd: Confirm/Request");
    310 	/*
    311 	 * if we're fragmenting then we already have an confirm request, just
    312 	 * return
    313 	 */
    314 	if (data->out_frag_pos)
    315 		return;
    316 
    317 	/* Each component of the cruft will be at most as big as the prime */
    318 	if (((cruft = os_malloc(BN_num_bytes(data->grp->prime))) == NULL) ||
    319 	    ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) {
    320 		wpa_printf(MSG_INFO, "EAP-PWD (server): debug allocation "
    321 			   "fail");
    322 		goto fin;
    323 	}
    324 
    325 	/*
    326 	 * commit is H(k | server_element | server_scalar | peer_element |
    327 	 *	       peer_scalar | ciphersuite)
    328 	 */
    329 	hash = eap_pwd_h_init();
    330 	if (hash == NULL)
    331 		goto fin;
    332 
    333 	/*
    334 	 * Zero the memory each time because this is mod prime math and some
    335 	 * value may start with a few zeros and the previous one did not.
    336 	 *
    337 	 * First is k
    338 	 */
    339 	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
    340 	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(data->k);
    341 	BN_bn2bin(data->k, cruft + offset);
    342 	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
    343 
    344 	/* server element: x, y */
    345 	if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
    346 						 data->my_element, x, y,
    347 						 data->bnctx)) {
    348 		wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
    349 			   "assignment fail");
    350 		goto fin;
    351 	}
    352 
    353 	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
    354 	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
    355 	BN_bn2bin(x, cruft + offset);
    356 	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
    357 	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
    358 	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
    359 	BN_bn2bin(y, cruft + offset);
    360 	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
    361 
    362 	/* server scalar */
    363 	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
    364 	offset = BN_num_bytes(data->grp->order) -
    365 		BN_num_bytes(data->my_scalar);
    366 	BN_bn2bin(data->my_scalar, cruft + offset);
    367 	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
    368 
    369 	/* peer element: x, y */
    370 	if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
    371 						 data->peer_element, x, y,
    372 						 data->bnctx)) {
    373 		wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
    374 			   "assignment fail");
    375 		goto fin;
    376 	}
    377 
    378 	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
    379 	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
    380 	BN_bn2bin(x, cruft + offset);
    381 	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
    382 	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
    383 	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
    384 	BN_bn2bin(y, cruft + offset);
    385 	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
    386 
    387 	/* peer scalar */
    388 	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
    389 	offset = BN_num_bytes(data->grp->order) -
    390 		BN_num_bytes(data->peer_scalar);
    391 	BN_bn2bin(data->peer_scalar, cruft + offset);
    392 	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
    393 
    394 	/* ciphersuite */
    395 	grp = htons(data->group_num);
    396 	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
    397 	ptr = cruft;
    398 	os_memcpy(ptr, &grp, sizeof(u16));
    399 	ptr += sizeof(u16);
    400 	*ptr = EAP_PWD_DEFAULT_RAND_FUNC;
    401 	ptr += sizeof(u8);
    402 	*ptr = EAP_PWD_DEFAULT_PRF;
    403 	ptr += sizeof(u8);
    404 	eap_pwd_h_update(hash, cruft, ptr - cruft);
    405 
    406 	/* all done with the random function */
    407 	eap_pwd_h_final(hash, conf);
    408 	os_memcpy(data->my_confirm, conf, SHA256_MAC_LEN);
    409 
    410 	data->outbuf = wpabuf_alloc(SHA256_MAC_LEN);
    411 	if (data->outbuf == NULL)
    412 		goto fin;
    413 
    414 	wpabuf_put_data(data->outbuf, conf, SHA256_MAC_LEN);
    415 
    416 fin:
    417 	bin_clear_free(cruft, BN_num_bytes(data->grp->prime));
    418 	BN_clear_free(x);
    419 	BN_clear_free(y);
    420 	if (data->outbuf == NULL)
    421 		eap_pwd_state(data, FAILURE);
    422 }
    423 
    424 
    425 static struct wpabuf *
    426 eap_pwd_build_req(struct eap_sm *sm, void *priv, u8 id)
    427 {
    428 	struct eap_pwd_data *data = priv;
    429 	struct wpabuf *req;
    430 	u8 lm_exch;
    431 	const u8 *buf;
    432 	u16 totlen = 0;
    433 	size_t len;
    434 
    435 	/*
    436 	 * if we're buffering response fragments then just ACK
    437 	 */
    438 	if (data->in_frag_pos) {
    439 		wpa_printf(MSG_DEBUG, "EAP-pwd: ACKing a fragment!!");
    440 		req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD,
    441 				    EAP_PWD_HDR_SIZE, EAP_CODE_REQUEST, id);
    442 		if (req == NULL) {
    443 			eap_pwd_state(data, FAILURE);
    444 			return NULL;
    445 		}
    446 		switch (data->state) {
    447 		case PWD_ID_Req:
    448 			wpabuf_put_u8(req, EAP_PWD_OPCODE_ID_EXCH);
    449 			break;
    450 		case PWD_Commit_Req:
    451 			wpabuf_put_u8(req, EAP_PWD_OPCODE_COMMIT_EXCH);
    452 			break;
    453 		case PWD_Confirm_Req:
    454 			wpabuf_put_u8(req, EAP_PWD_OPCODE_CONFIRM_EXCH);
    455 			break;
    456 		default:
    457 			eap_pwd_state(data, FAILURE);   /* just to be sure */
    458 			wpabuf_free(req);
    459 			return NULL;
    460 		}
    461 		return req;
    462 	}
    463 
    464 	/*
    465 	 * build the data portion of a request
    466 	 */
    467 	switch (data->state) {
    468 	case PWD_ID_Req:
    469 		eap_pwd_build_id_req(sm, data, id);
    470 		lm_exch = EAP_PWD_OPCODE_ID_EXCH;
    471 		break;
    472 	case PWD_Commit_Req:
    473 		eap_pwd_build_commit_req(sm, data, id);
    474 		lm_exch = EAP_PWD_OPCODE_COMMIT_EXCH;
    475 		break;
    476 	case PWD_Confirm_Req:
    477 		eap_pwd_build_confirm_req(sm, data, id);
    478 		lm_exch = EAP_PWD_OPCODE_CONFIRM_EXCH;
    479 		break;
    480 	default:
    481 		wpa_printf(MSG_INFO, "EAP-pwd: Unknown state %d in build_req",
    482 			   data->state);
    483 		eap_pwd_state(data, FAILURE);
    484 		lm_exch = 0;    /* hush now, sweet compiler */
    485 		break;
    486 	}
    487 
    488 	if (data->state == FAILURE)
    489 		return NULL;
    490 
    491 	/*
    492 	 * determine whether that data needs to be fragmented
    493 	 */
    494 	len = wpabuf_len(data->outbuf) - data->out_frag_pos;
    495 	if ((len + EAP_PWD_HDR_SIZE) > data->mtu) {
    496 		len = data->mtu - EAP_PWD_HDR_SIZE;
    497 		EAP_PWD_SET_MORE_BIT(lm_exch);
    498 		/*
    499 		 * if this is the first fragment, need to set the M bit
    500 		 * and add the total length to the eap_pwd_hdr
    501 		 */
    502 		if (data->out_frag_pos == 0) {
    503 			EAP_PWD_SET_LENGTH_BIT(lm_exch);
    504 			totlen = wpabuf_len(data->outbuf) +
    505 				EAP_PWD_HDR_SIZE + sizeof(u16);
    506 			len -= sizeof(u16);
    507 			wpa_printf(MSG_DEBUG, "EAP-pwd: Fragmenting output, "
    508 				   "total length = %d", totlen);
    509 		}
    510 		wpa_printf(MSG_DEBUG, "EAP-pwd: Send a %d byte fragment",
    511 			   (int) len);
    512 	}
    513 
    514 	/*
    515 	 * alloc an eap request and populate it with the data
    516 	 */
    517 	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD,
    518 			    EAP_PWD_HDR_SIZE + len +
    519 			    (totlen ? sizeof(u16) : 0),
    520 			    EAP_CODE_REQUEST, id);
    521 	if (req == NULL) {
    522 		eap_pwd_state(data, FAILURE);
    523 		return NULL;
    524 	}
    525 
    526 	wpabuf_put_u8(req, lm_exch);
    527 	if (EAP_PWD_GET_LENGTH_BIT(lm_exch))
    528 		wpabuf_put_be16(req, totlen);
    529 
    530 	buf = wpabuf_head_u8(data->outbuf);
    531 	wpabuf_put_data(req, buf + data->out_frag_pos, len);
    532 	data->out_frag_pos += len;
    533 	/*
    534 	 * either not fragged or last fragment, either way free up the data
    535 	 */
    536 	if (data->out_frag_pos >= wpabuf_len(data->outbuf)) {
    537 		wpabuf_free(data->outbuf);
    538 		data->outbuf = NULL;
    539 		data->out_frag_pos = 0;
    540 	}
    541 
    542 	return req;
    543 }
    544 
    545 
    546 static Boolean eap_pwd_check(struct eap_sm *sm, void *priv,
    547 			     struct wpabuf *respData)
    548 {
    549 	struct eap_pwd_data *data = priv;
    550 	const u8 *pos;
    551 	size_t len;
    552 
    553 	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PWD, respData, &len);
    554 	if (pos == NULL || len < 1) {
    555 		wpa_printf(MSG_INFO, "EAP-pwd: Invalid frame");
    556 		return TRUE;
    557 	}
    558 
    559 	wpa_printf(MSG_DEBUG, "EAP-pwd: Received frame: exch = %d, len = %d",
    560 		   EAP_PWD_GET_EXCHANGE(*pos), (int) len);
    561 
    562 	if (data->state == PWD_ID_Req &&
    563 	    ((EAP_PWD_GET_EXCHANGE(*pos)) == EAP_PWD_OPCODE_ID_EXCH))
    564 		return FALSE;
    565 
    566 	if (data->state == PWD_Commit_Req &&
    567 	    ((EAP_PWD_GET_EXCHANGE(*pos)) == EAP_PWD_OPCODE_COMMIT_EXCH))
    568 		return FALSE;
    569 
    570 	if (data->state == PWD_Confirm_Req &&
    571 	    ((EAP_PWD_GET_EXCHANGE(*pos)) == EAP_PWD_OPCODE_CONFIRM_EXCH))
    572 		return FALSE;
    573 
    574 	wpa_printf(MSG_INFO, "EAP-pwd: Unexpected opcode=%d in state=%d",
    575 		   *pos, data->state);
    576 
    577 	return TRUE;
    578 }
    579 
    580 
    581 static void eap_pwd_process_id_resp(struct eap_sm *sm,
    582 				    struct eap_pwd_data *data,
    583 				    const u8 *payload, size_t payload_len)
    584 {
    585 	struct eap_pwd_id *id;
    586 	const u8 *password;
    587 	size_t password_len;
    588 	u8 pwhashhash[16];
    589 	int res;
    590 
    591 	if (payload_len < sizeof(struct eap_pwd_id)) {
    592 		wpa_printf(MSG_INFO, "EAP-pwd: Invalid ID response");
    593 		return;
    594 	}
    595 
    596 	id = (struct eap_pwd_id *) payload;
    597 	if ((data->group_num != be_to_host16(id->group_num)) ||
    598 	    (id->random_function != EAP_PWD_DEFAULT_RAND_FUNC) ||
    599 	    (os_memcmp(id->token, (u8 *)&data->token, sizeof(data->token))) ||
    600 	    (id->prf != EAP_PWD_DEFAULT_PRF)) {
    601 		wpa_printf(MSG_INFO, "EAP-pwd: peer changed parameters");
    602 		eap_pwd_state(data, FAILURE);
    603 		return;
    604 	}
    605 	data->id_peer = os_malloc(payload_len - sizeof(struct eap_pwd_id));
    606 	if (data->id_peer == NULL) {
    607 		wpa_printf(MSG_INFO, "EAP-PWD: memory allocation id fail");
    608 		return;
    609 	}
    610 	data->id_peer_len = payload_len - sizeof(struct eap_pwd_id);
    611 	os_memcpy(data->id_peer, id->identity, data->id_peer_len);
    612 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-PWD (server): peer sent id of",
    613 			  data->id_peer, data->id_peer_len);
    614 
    615 	data->grp = os_zalloc(sizeof(EAP_PWD_group));
    616 	if (data->grp == NULL) {
    617 		wpa_printf(MSG_INFO, "EAP-PWD: failed to allocate memory for "
    618 			   "group");
    619 		return;
    620 	}
    621 
    622 	if (data->password_hash) {
    623 		res = hash_nt_password_hash(data->password, pwhashhash);
    624 		if (res)
    625 			return;
    626 		password = pwhashhash;
    627 		password_len = sizeof(pwhashhash);
    628 	} else {
    629 		password = data->password;
    630 		password_len = data->password_len;
    631 	}
    632 
    633 	res = compute_password_element(data->grp, data->group_num,
    634 				       password, password_len,
    635 				       data->id_server, data->id_server_len,
    636 				       data->id_peer, data->id_peer_len,
    637 				       (u8 *) &data->token);
    638 	os_memset(pwhashhash, 0, sizeof(pwhashhash));
    639 	if (res) {
    640 		wpa_printf(MSG_INFO, "EAP-PWD (server): unable to compute "
    641 			   "PWE");
    642 		return;
    643 	}
    644 	wpa_printf(MSG_DEBUG, "EAP-PWD (server): computed %d bit PWE...",
    645 		   BN_num_bits(data->grp->prime));
    646 
    647 	eap_pwd_state(data, PWD_Commit_Req);
    648 }
    649 
    650 
    651 static void
    652 eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data,
    653 			    const u8 *payload, size_t payload_len)
    654 {
    655 	u8 *ptr;
    656 	BIGNUM *x = NULL, *y = NULL, *cofactor = NULL;
    657 	EC_POINT *K = NULL, *point = NULL;
    658 	int res = 0;
    659 	size_t prime_len, order_len;
    660 
    661 	wpa_printf(MSG_DEBUG, "EAP-pwd: Received commit response");
    662 
    663 	prime_len = BN_num_bytes(data->grp->prime);
    664 	order_len = BN_num_bytes(data->grp->order);
    665 
    666 	if (payload_len != 2 * prime_len + order_len) {
    667 		wpa_printf(MSG_INFO,
    668 			   "EAP-pwd: Unexpected Commit payload length %u (expected %u)",
    669 			   (unsigned int) payload_len,
    670 			   (unsigned int) (2 * prime_len + order_len));
    671 		goto fin;
    672 	}
    673 
    674 	if (((data->peer_scalar = BN_new()) == NULL) ||
    675 	    ((data->k = BN_new()) == NULL) ||
    676 	    ((cofactor = BN_new()) == NULL) ||
    677 	    ((x = BN_new()) == NULL) ||
    678 	    ((y = BN_new()) == NULL) ||
    679 	    ((point = EC_POINT_new(data->grp->group)) == NULL) ||
    680 	    ((K = EC_POINT_new(data->grp->group)) == NULL) ||
    681 	    ((data->peer_element = EC_POINT_new(data->grp->group)) == NULL)) {
    682 		wpa_printf(MSG_INFO, "EAP-PWD (server): peer data allocation "
    683 			   "fail");
    684 		goto fin;
    685 	}
    686 
    687 	if (!EC_GROUP_get_cofactor(data->grp->group, cofactor, NULL)) {
    688 		wpa_printf(MSG_INFO, "EAP-PWD (server): unable to get "
    689 			   "cofactor for curve");
    690 		goto fin;
    691 	}
    692 
    693 	/* element, x then y, followed by scalar */
    694 	ptr = (u8 *) payload;
    695 	BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), x);
    696 	ptr += BN_num_bytes(data->grp->prime);
    697 	BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), y);
    698 	ptr += BN_num_bytes(data->grp->prime);
    699 	BN_bin2bn(ptr, BN_num_bytes(data->grp->order), data->peer_scalar);
    700 	if (!EC_POINT_set_affine_coordinates_GFp(data->grp->group,
    701 						 data->peer_element, x, y,
    702 						 data->bnctx)) {
    703 		wpa_printf(MSG_INFO, "EAP-PWD (server): setting peer element "
    704 			   "fail");
    705 		goto fin;
    706 	}
    707 
    708 	/* check to ensure peer's element is not in a small sub-group */
    709 	if (BN_cmp(cofactor, BN_value_one())) {
    710 		if (!EC_POINT_mul(data->grp->group, point, NULL,
    711 				  data->peer_element, cofactor, NULL)) {
    712 			wpa_printf(MSG_INFO, "EAP-PWD (server): cannot "
    713 				   "multiply peer element by order");
    714 			goto fin;
    715 		}
    716 		if (EC_POINT_is_at_infinity(data->grp->group, point)) {
    717 			wpa_printf(MSG_INFO, "EAP-PWD (server): peer element "
    718 				   "is at infinity!\n");
    719 			goto fin;
    720 		}
    721 	}
    722 
    723 	/* compute the shared key, k */
    724 	if ((!EC_POINT_mul(data->grp->group, K, NULL, data->grp->pwe,
    725 			   data->peer_scalar, data->bnctx)) ||
    726 	    (!EC_POINT_add(data->grp->group, K, K, data->peer_element,
    727 			   data->bnctx)) ||
    728 	    (!EC_POINT_mul(data->grp->group, K, NULL, K, data->private_value,
    729 			   data->bnctx))) {
    730 		wpa_printf(MSG_INFO, "EAP-PWD (server): computing shared key "
    731 			   "fail");
    732 		goto fin;
    733 	}
    734 
    735 	/* ensure that the shared key isn't in a small sub-group */
    736 	if (BN_cmp(cofactor, BN_value_one())) {
    737 		if (!EC_POINT_mul(data->grp->group, K, NULL, K, cofactor,
    738 				  NULL)) {
    739 			wpa_printf(MSG_INFO, "EAP-PWD (server): cannot "
    740 				   "multiply shared key point by order!\n");
    741 			goto fin;
    742 		}
    743 	}
    744 
    745 	/*
    746 	 * This check is strictly speaking just for the case above where
    747 	 * co-factor > 1 but it was suggested that even though this is probably
    748 	 * never going to happen it is a simple and safe check "just to be
    749 	 * sure" so let's be safe.
    750 	 */
    751 	if (EC_POINT_is_at_infinity(data->grp->group, K)) {
    752 		wpa_printf(MSG_INFO, "EAP-PWD (server): shared key point is "
    753 			   "at infinity");
    754 		goto fin;
    755 	}
    756 	if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, K, data->k,
    757 						 NULL, data->bnctx)) {
    758 		wpa_printf(MSG_INFO, "EAP-PWD (server): unable to extract "
    759 			   "shared secret from secret point");
    760 		goto fin;
    761 	}
    762 	res = 1;
    763 
    764 fin:
    765 	EC_POINT_clear_free(K);
    766 	EC_POINT_clear_free(point);
    767 	BN_clear_free(cofactor);
    768 	BN_clear_free(x);
    769 	BN_clear_free(y);
    770 
    771 	if (res)
    772 		eap_pwd_state(data, PWD_Confirm_Req);
    773 	else
    774 		eap_pwd_state(data, FAILURE);
    775 }
    776 
    777 
    778 static void
    779 eap_pwd_process_confirm_resp(struct eap_sm *sm, struct eap_pwd_data *data,
    780 			     const u8 *payload, size_t payload_len)
    781 {
    782 	BIGNUM *x = NULL, *y = NULL;
    783 	struct crypto_hash *hash;
    784 	u32 cs;
    785 	u16 grp;
    786 	u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr;
    787 	int offset;
    788 
    789 	if (payload_len != SHA256_MAC_LEN) {
    790 		wpa_printf(MSG_INFO,
    791 			   "EAP-pwd: Unexpected Confirm payload length %u (expected %u)",
    792 			   (unsigned int) payload_len, SHA256_MAC_LEN);
    793 		goto fin;
    794 	}
    795 
    796 	/* build up the ciphersuite: group | random_function | prf */
    797 	grp = htons(data->group_num);
    798 	ptr = (u8 *) &cs;
    799 	os_memcpy(ptr, &grp, sizeof(u16));
    800 	ptr += sizeof(u16);
    801 	*ptr = EAP_PWD_DEFAULT_RAND_FUNC;
    802 	ptr += sizeof(u8);
    803 	*ptr = EAP_PWD_DEFAULT_PRF;
    804 
    805 	/* each component of the cruft will be at most as big as the prime */
    806 	if (((cruft = os_malloc(BN_num_bytes(data->grp->prime))) == NULL) ||
    807 	    ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) {
    808 		wpa_printf(MSG_INFO, "EAP-PWD (peer): allocation fail");
    809 		goto fin;
    810 	}
    811 
    812 	/*
    813 	 * commit is H(k | peer_element | peer_scalar | server_element |
    814 	 *	       server_scalar | ciphersuite)
    815 	 */
    816 	hash = eap_pwd_h_init();
    817 	if (hash == NULL)
    818 		goto fin;
    819 
    820 	/* k */
    821 	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
    822 	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(data->k);
    823 	BN_bn2bin(data->k, cruft + offset);
    824 	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
    825 
    826 	/* peer element: x, y */
    827 	if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
    828 						 data->peer_element, x, y,
    829 						 data->bnctx)) {
    830 		wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
    831 			   "assignment fail");
    832 		goto fin;
    833 	}
    834 	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
    835 	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
    836 	BN_bn2bin(x, cruft + offset);
    837 	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
    838 	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
    839 	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
    840 	BN_bn2bin(y, cruft + offset);
    841 	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
    842 
    843 	/* peer scalar */
    844 	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
    845 	offset = BN_num_bytes(data->grp->order) -
    846 		BN_num_bytes(data->peer_scalar);
    847 	BN_bn2bin(data->peer_scalar, cruft + offset);
    848 	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
    849 
    850 	/* server element: x, y */
    851 	if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
    852 						 data->my_element, x, y,
    853 						 data->bnctx)) {
    854 		wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
    855 			   "assignment fail");
    856 		goto fin;
    857 	}
    858 
    859 	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
    860 	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
    861 	BN_bn2bin(x, cruft + offset);
    862 	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
    863 	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
    864 	offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
    865 	BN_bn2bin(y, cruft + offset);
    866 	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
    867 
    868 	/* server scalar */
    869 	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
    870 	offset = BN_num_bytes(data->grp->order) -
    871 		BN_num_bytes(data->my_scalar);
    872 	BN_bn2bin(data->my_scalar, cruft + offset);
    873 	eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
    874 
    875 	/* ciphersuite */
    876 	os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
    877 	eap_pwd_h_update(hash, (u8 *) &cs, sizeof(u32));
    878 
    879 	/* all done */
    880 	eap_pwd_h_final(hash, conf);
    881 
    882 	ptr = (u8 *) payload;
    883 	if (os_memcmp_const(conf, ptr, SHA256_MAC_LEN)) {
    884 		wpa_printf(MSG_INFO, "EAP-PWD (server): confirm did not "
    885 			   "verify");
    886 		goto fin;
    887 	}
    888 
    889 	wpa_printf(MSG_DEBUG, "EAP-pwd (server): confirm verified");
    890 	if (compute_keys(data->grp, data->bnctx, data->k,
    891 			 data->peer_scalar, data->my_scalar, conf,
    892 			 data->my_confirm, &cs, data->msk, data->emsk,
    893 			 data->session_id) < 0)
    894 		eap_pwd_state(data, FAILURE);
    895 	else
    896 		eap_pwd_state(data, SUCCESS);
    897 
    898 fin:
    899 	bin_clear_free(cruft, BN_num_bytes(data->grp->prime));
    900 	BN_clear_free(x);
    901 	BN_clear_free(y);
    902 }
    903 
    904 
    905 static void eap_pwd_process(struct eap_sm *sm, void *priv,
    906 			    struct wpabuf *respData)
    907 {
    908 	struct eap_pwd_data *data = priv;
    909 	const u8 *pos;
    910 	size_t len;
    911 	u8 lm_exch;
    912 	u16 tot_len;
    913 
    914 	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PWD, respData, &len);
    915 	if ((pos == NULL) || (len < 1)) {
    916 		wpa_printf(MSG_INFO, "Bad EAP header! pos %s and len = %d",
    917 			   (pos == NULL) ? "is NULL" : "is not NULL",
    918 			   (int) len);
    919 		return;
    920 	}
    921 
    922 	lm_exch = *pos;
    923 	pos++;            /* skip over the bits and the exch */
    924 	len--;
    925 
    926 	/*
    927 	 * if we're fragmenting then this should be an ACK with no data,
    928 	 * just return and continue fragmenting in the "build" section above
    929 	 */
    930 	if (data->out_frag_pos) {
    931 		if (len > 1)
    932 			wpa_printf(MSG_INFO, "EAP-pwd: Bad response! "
    933 				   "Fragmenting but not an ACK");
    934 		else
    935 			wpa_printf(MSG_DEBUG, "EAP-pwd: received ACK from "
    936 				   "peer");
    937 		return;
    938 	}
    939 	/*
    940 	 * if we're receiving fragmented packets then we need to buffer...
    941 	 *
    942 	 * the first fragment has a total length
    943 	 */
    944 	if (EAP_PWD_GET_LENGTH_BIT(lm_exch)) {
    945 		if (len < 2) {
    946 			wpa_printf(MSG_DEBUG,
    947 				   "EAP-pwd: Frame too short to contain Total-Length field");
    948 			return;
    949 		}
    950 		tot_len = WPA_GET_BE16(pos);
    951 		wpa_printf(MSG_DEBUG, "EAP-pwd: Incoming fragments, total "
    952 			   "length = %d", tot_len);
    953 		if (tot_len > 15000)
    954 			return;
    955 		if (data->inbuf) {
    956 			wpa_printf(MSG_DEBUG,
    957 				   "EAP-pwd: Unexpected new fragment start when previous fragment is still in use");
    958 			return;
    959 		}
    960 		data->inbuf = wpabuf_alloc(tot_len);
    961 		if (data->inbuf == NULL) {
    962 			wpa_printf(MSG_INFO, "EAP-pwd: Out of memory to "
    963 				   "buffer fragments!");
    964 			return;
    965 		}
    966 		data->in_frag_pos = 0;
    967 		pos += sizeof(u16);
    968 		len -= sizeof(u16);
    969 	}
    970 	/*
    971 	 * the first and all intermediate fragments have the M bit set
    972 	 */
    973 	if (EAP_PWD_GET_MORE_BIT(lm_exch)) {
    974 		if ((data->in_frag_pos + len) > wpabuf_size(data->inbuf)) {
    975 			wpa_printf(MSG_DEBUG, "EAP-pwd: Buffer overflow "
    976 				   "attack detected! (%d+%d > %d)",
    977 				   (int) data->in_frag_pos, (int) len,
    978 				   (int) wpabuf_size(data->inbuf));
    979 			eap_pwd_state(data, FAILURE);
    980 			return;
    981 		}
    982 		wpabuf_put_data(data->inbuf, pos, len);
    983 		data->in_frag_pos += len;
    984 		wpa_printf(MSG_DEBUG, "EAP-pwd: Got a %d byte fragment",
    985 			   (int) len);
    986 		return;
    987 	}
    988 	/*
    989 	 * last fragment won't have the M bit set (but we're obviously
    990 	 * buffering fragments so that's how we know it's the last)
    991 	 */
    992 	if (data->in_frag_pos) {
    993 		wpabuf_put_data(data->inbuf, pos, len);
    994 		data->in_frag_pos += len;
    995 		pos = wpabuf_head_u8(data->inbuf);
    996 		len = data->in_frag_pos;
    997 		wpa_printf(MSG_DEBUG, "EAP-pwd: Last fragment, %d bytes",
    998 			   (int) len);
    999 	}
   1000 	switch (EAP_PWD_GET_EXCHANGE(lm_exch)) {
   1001 	case EAP_PWD_OPCODE_ID_EXCH:
   1002 		eap_pwd_process_id_resp(sm, data, pos, len);
   1003 		break;
   1004 	case EAP_PWD_OPCODE_COMMIT_EXCH:
   1005 		eap_pwd_process_commit_resp(sm, data, pos, len);
   1006 		break;
   1007 	case EAP_PWD_OPCODE_CONFIRM_EXCH:
   1008 		eap_pwd_process_confirm_resp(sm, data, pos, len);
   1009 		break;
   1010 	}
   1011 	/*
   1012 	 * if we had been buffering fragments, here's a great place
   1013 	 * to clean up
   1014 	 */
   1015 	if (data->in_frag_pos) {
   1016 		wpabuf_free(data->inbuf);
   1017 		data->inbuf = NULL;
   1018 		data->in_frag_pos = 0;
   1019 	}
   1020 }
   1021 
   1022 
   1023 static u8 * eap_pwd_getkey(struct eap_sm *sm, void *priv, size_t *len)
   1024 {
   1025 	struct eap_pwd_data *data = priv;
   1026 	u8 *key;
   1027 
   1028 	if (data->state != SUCCESS)
   1029 		return NULL;
   1030 
   1031 	key = os_malloc(EAP_MSK_LEN);
   1032 	if (key == NULL)
   1033 		return NULL;
   1034 
   1035 	os_memcpy(key, data->msk, EAP_MSK_LEN);
   1036 	*len = EAP_MSK_LEN;
   1037 
   1038 	return key;
   1039 }
   1040 
   1041 
   1042 static u8 * eap_pwd_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
   1043 {
   1044 	struct eap_pwd_data *data = priv;
   1045 	u8 *key;
   1046 
   1047 	if (data->state != SUCCESS)
   1048 		return NULL;
   1049 
   1050 	key = os_malloc(EAP_EMSK_LEN);
   1051 	if (key == NULL)
   1052 		return NULL;
   1053 
   1054 	os_memcpy(key, data->emsk, EAP_EMSK_LEN);
   1055 	*len = EAP_EMSK_LEN;
   1056 
   1057 	return key;
   1058 }
   1059 
   1060 
   1061 static Boolean eap_pwd_is_success(struct eap_sm *sm, void *priv)
   1062 {
   1063 	struct eap_pwd_data *data = priv;
   1064 	return data->state == SUCCESS;
   1065 }
   1066 
   1067 
   1068 static Boolean eap_pwd_is_done(struct eap_sm *sm, void *priv)
   1069 {
   1070 	struct eap_pwd_data *data = priv;
   1071 	return (data->state == SUCCESS) || (data->state == FAILURE);
   1072 }
   1073 
   1074 
   1075 static u8 * eap_pwd_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
   1076 {
   1077 	struct eap_pwd_data *data = priv;
   1078 	u8 *id;
   1079 
   1080 	if (data->state != SUCCESS)
   1081 		return NULL;
   1082 
   1083 	id = os_malloc(1 + SHA256_MAC_LEN);
   1084 	if (id == NULL)
   1085 		return NULL;
   1086 
   1087 	os_memcpy(id, data->session_id, 1 + SHA256_MAC_LEN);
   1088 	*len = 1 + SHA256_MAC_LEN;
   1089 
   1090 	return id;
   1091 }
   1092 
   1093 
   1094 int eap_server_pwd_register(void)
   1095 {
   1096 	struct eap_method *eap;
   1097 	int ret;
   1098 	struct timeval tp;
   1099 	struct timezone tz;
   1100 	u32 sr;
   1101 
   1102 	sr = 0xdeaddada;
   1103 	(void) gettimeofday(&tp, &tz);
   1104 	sr ^= (tp.tv_sec ^ tp.tv_usec);
   1105 	srandom(sr);
   1106 
   1107 	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
   1108 				      EAP_VENDOR_IETF, EAP_TYPE_PWD,
   1109 				      "PWD");
   1110 	if (eap == NULL)
   1111 		return -1;
   1112 
   1113 	eap->init = eap_pwd_init;
   1114 	eap->reset = eap_pwd_reset;
   1115 	eap->buildReq = eap_pwd_build_req;
   1116 	eap->check = eap_pwd_check;
   1117 	eap->process = eap_pwd_process;
   1118 	eap->isDone = eap_pwd_is_done;
   1119 	eap->getKey = eap_pwd_getkey;
   1120 	eap->get_emsk = eap_pwd_get_emsk;
   1121 	eap->isSuccess = eap_pwd_is_success;
   1122 	eap->getSessionId = eap_pwd_get_session_id;
   1123 
   1124 	ret = eap_server_method_register(eap);
   1125 	if (ret)
   1126 		eap_server_method_free(eap);
   1127 	return ret;
   1128 }
   1129 
   1130