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