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