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