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 crypto_bignum_to_bin(data->my_scalar, scalar, order_len, order_len); 670 if (crypto_ec_point_to_bin(data->grp->group, data->my_element, element, 671 element + prime_len) != 0) { 672 wpa_printf(MSG_INFO, "EAP-PWD (peer): point assignment fail"); 673 goto fin; 674 } 675 676 fin: 677 crypto_bignum_deinit(mask, 1); 678 crypto_ec_point_deinit(K, 1); 679 if (data->outbuf == NULL) 680 eap_pwd_state(data, FAILURE); 681 else 682 eap_pwd_state(data, PWD_Confirm_Req); 683 } 684 685 686 static void 687 eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data, 688 struct eap_method_ret *ret, 689 const struct wpabuf *reqData, 690 const u8 *payload, size_t payload_len) 691 { 692 struct crypto_hash *hash = NULL; 693 u32 cs; 694 u16 grp; 695 u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr; 696 size_t prime_len = 0, order_len = 0; 697 698 if (data->state != PWD_Confirm_Req) { 699 ret->ignore = TRUE; 700 goto fin; 701 } 702 703 if (payload_len != SHA256_MAC_LEN) { 704 wpa_printf(MSG_INFO, 705 "EAP-pwd: Unexpected Confirm payload length %u (expected %u)", 706 (unsigned int) payload_len, SHA256_MAC_LEN); 707 goto fin; 708 } 709 710 prime_len = crypto_ec_prime_len(data->grp->group); 711 order_len = crypto_ec_order_len(data->grp->group); 712 713 /* 714 * first build up the ciphersuite which is group | random_function | 715 * prf 716 */ 717 grp = htons(data->group_num); 718 ptr = (u8 *) &cs; 719 os_memcpy(ptr, &grp, sizeof(u16)); 720 ptr += sizeof(u16); 721 *ptr = EAP_PWD_DEFAULT_RAND_FUNC; 722 ptr += sizeof(u8); 723 *ptr = EAP_PWD_DEFAULT_PRF; 724 725 /* each component of the point will be at most as big as the prime */ 726 cruft = os_malloc(prime_len * 2); 727 if (!cruft) { 728 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm allocation " 729 "fail"); 730 goto fin; 731 } 732 733 /* 734 * server's commit is H(k | server_element | server_scalar | 735 * peer_element | peer_scalar | ciphersuite) 736 */ 737 hash = eap_pwd_h_init(); 738 if (hash == NULL) 739 goto fin; 740 741 /* 742 * zero the memory each time because this is mod prime math and some 743 * value may start with a few zeros and the previous one did not. 744 */ 745 crypto_bignum_to_bin(data->k, cruft, prime_len, prime_len); 746 eap_pwd_h_update(hash, cruft, prime_len); 747 748 /* server element: x, y */ 749 if (crypto_ec_point_to_bin(data->grp->group, data->server_element, 750 cruft, cruft + prime_len) != 0) { 751 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point " 752 "assignment fail"); 753 goto fin; 754 } 755 eap_pwd_h_update(hash, cruft, prime_len * 2); 756 757 /* server scalar */ 758 crypto_bignum_to_bin(data->server_scalar, cruft, order_len, order_len); 759 eap_pwd_h_update(hash, cruft, order_len); 760 761 /* my element: x, y */ 762 if (crypto_ec_point_to_bin(data->grp->group, data->my_element, cruft, 763 cruft + prime_len) != 0) { 764 wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point " 765 "assignment fail"); 766 goto fin; 767 } 768 eap_pwd_h_update(hash, cruft, prime_len * 2); 769 770 /* my scalar */ 771 crypto_bignum_to_bin(data->my_scalar, cruft, order_len, order_len); 772 eap_pwd_h_update(hash, cruft, order_len); 773 774 /* the ciphersuite */ 775 eap_pwd_h_update(hash, (u8 *) &cs, sizeof(u32)); 776 777 /* random function fin */ 778 eap_pwd_h_final(hash, conf); 779 hash = NULL; 780 781 ptr = (u8 *) payload; 782 if (os_memcmp_const(conf, ptr, SHA256_MAC_LEN)) { 783 wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm did not verify"); 784 goto fin; 785 } 786 787 wpa_printf(MSG_DEBUG, "EAP-pwd (peer): confirm verified"); 788 789 /* 790 * compute confirm: 791 * H(k | peer_element | peer_scalar | server_element | server_scalar | 792 * ciphersuite) 793 */ 794 hash = eap_pwd_h_init(); 795 if (hash == NULL) 796 goto fin; 797 798 /* k */ 799 crypto_bignum_to_bin(data->k, cruft, prime_len, prime_len); 800 eap_pwd_h_update(hash, cruft, prime_len); 801 802 /* my element */ 803 if (crypto_ec_point_to_bin(data->grp->group, data->my_element, cruft, 804 cruft + prime_len) != 0) { 805 wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm point " 806 "assignment fail"); 807 goto fin; 808 } 809 eap_pwd_h_update(hash, cruft, prime_len * 2); 810 811 /* my scalar */ 812 crypto_bignum_to_bin(data->my_scalar, cruft, order_len, order_len); 813 eap_pwd_h_update(hash, cruft, order_len); 814 815 /* server element: x, y */ 816 if (crypto_ec_point_to_bin(data->grp->group, data->server_element, 817 cruft, 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 /* server scalar */ 825 crypto_bignum_to_bin(data->server_scalar, cruft, order_len, order_len); 826 eap_pwd_h_update(hash, cruft, order_len); 827 828 /* the ciphersuite */ 829 eap_pwd_h_update(hash, (u8 *) &cs, sizeof(u32)); 830 831 /* all done */ 832 eap_pwd_h_final(hash, conf); 833 hash = NULL; 834 835 if (compute_keys(data->grp, data->k, 836 data->my_scalar, data->server_scalar, conf, ptr, 837 &cs, data->msk, data->emsk, data->session_id) < 0) { 838 wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to compute MSK | " 839 "EMSK"); 840 goto fin; 841 } 842 843 data->outbuf = wpabuf_alloc(SHA256_MAC_LEN); 844 if (data->outbuf == NULL) 845 goto fin; 846 847 wpabuf_put_data(data->outbuf, conf, SHA256_MAC_LEN); 848 849 fin: 850 bin_clear_free(cruft, prime_len * 2); 851 if (data->outbuf == NULL) { 852 ret->methodState = METHOD_DONE; 853 ret->decision = DECISION_FAIL; 854 eap_pwd_state(data, FAILURE); 855 } else { 856 eap_pwd_state(data, SUCCESS_ON_FRAG_COMPLETION); 857 } 858 859 /* clean allocated memory */ 860 if (hash) 861 eap_pwd_h_final(hash, conf); 862 } 863 864 865 static struct wpabuf * 866 eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, 867 const struct wpabuf *reqData) 868 { 869 struct eap_pwd_data *data = priv; 870 struct wpabuf *resp = NULL; 871 const u8 *pos, *buf; 872 size_t len; 873 u16 tot_len = 0; 874 u8 lm_exch; 875 876 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PWD, reqData, &len); 877 if ((pos == NULL) || (len < 1)) { 878 wpa_printf(MSG_DEBUG, "EAP-pwd: Got a frame but pos is %s and " 879 "len is %d", 880 pos == NULL ? "NULL" : "not NULL", (int) len); 881 ret->ignore = TRUE; 882 return NULL; 883 } 884 885 ret->ignore = FALSE; 886 ret->methodState = METHOD_MAY_CONT; 887 ret->decision = DECISION_FAIL; 888 ret->allowNotifications = FALSE; 889 890 lm_exch = *pos; 891 pos++; /* skip over the bits and the exch */ 892 len--; 893 894 /* 895 * we're fragmenting so send out the next fragment 896 */ 897 if (data->out_frag_pos) { 898 /* 899 * this should be an ACK 900 */ 901 if (len) 902 wpa_printf(MSG_INFO, "Bad Response! Fragmenting but " 903 "not an ACK"); 904 905 wpa_printf(MSG_DEBUG, "EAP-pwd: Got an ACK for a fragment"); 906 /* 907 * check if there are going to be more fragments 908 */ 909 len = wpabuf_len(data->outbuf) - data->out_frag_pos; 910 if ((len + EAP_PWD_HDR_SIZE) > data->mtu) { 911 len = data->mtu - EAP_PWD_HDR_SIZE; 912 EAP_PWD_SET_MORE_BIT(lm_exch); 913 } 914 resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, 915 EAP_PWD_HDR_SIZE + len, 916 EAP_CODE_RESPONSE, eap_get_id(reqData)); 917 if (resp == NULL) { 918 wpa_printf(MSG_INFO, "Unable to allocate memory for " 919 "next fragment!"); 920 return NULL; 921 } 922 wpabuf_put_u8(resp, lm_exch); 923 buf = wpabuf_head_u8(data->outbuf); 924 wpabuf_put_data(resp, buf + data->out_frag_pos, len); 925 data->out_frag_pos += len; 926 /* 927 * this is the last fragment so get rid of the out buffer 928 */ 929 if (data->out_frag_pos >= wpabuf_len(data->outbuf)) { 930 wpabuf_free(data->outbuf); 931 data->outbuf = NULL; 932 data->out_frag_pos = 0; 933 } 934 wpa_printf(MSG_DEBUG, "EAP-pwd: Send %s fragment of %d bytes", 935 data->out_frag_pos == 0 ? "last" : "next", 936 (int) len); 937 if (data->state == SUCCESS_ON_FRAG_COMPLETION) { 938 ret->methodState = METHOD_DONE; 939 ret->decision = DECISION_UNCOND_SUCC; 940 eap_pwd_state(data, SUCCESS); 941 } 942 return resp; 943 } 944 945 /* 946 * see if this is a fragment that needs buffering 947 * 948 * if it's the first fragment there'll be a length field 949 */ 950 if (EAP_PWD_GET_LENGTH_BIT(lm_exch)) { 951 if (len < 2) { 952 wpa_printf(MSG_DEBUG, 953 "EAP-pwd: Frame too short to contain Total-Length field"); 954 ret->ignore = TRUE; 955 return NULL; 956 } 957 tot_len = WPA_GET_BE16(pos); 958 wpa_printf(MSG_DEBUG, "EAP-pwd: Incoming fragments whose " 959 "total length = %d", tot_len); 960 if (tot_len > 15000) 961 return NULL; 962 if (data->inbuf) { 963 wpa_printf(MSG_DEBUG, 964 "EAP-pwd: Unexpected new fragment start when previous fragment is still in use"); 965 ret->ignore = TRUE; 966 return NULL; 967 } 968 data->inbuf = wpabuf_alloc(tot_len); 969 if (data->inbuf == NULL) { 970 wpa_printf(MSG_INFO, "Out of memory to buffer " 971 "fragments!"); 972 return NULL; 973 } 974 data->in_frag_pos = 0; 975 pos += sizeof(u16); 976 len -= sizeof(u16); 977 } 978 /* 979 * buffer and ACK the fragment 980 */ 981 if (EAP_PWD_GET_MORE_BIT(lm_exch) || data->in_frag_pos) { 982 if (!data->inbuf) { 983 wpa_printf(MSG_DEBUG, 984 "EAP-pwd: No buffer for reassembly"); 985 ret->methodState = METHOD_DONE; 986 ret->decision = DECISION_FAIL; 987 return NULL; 988 } 989 data->in_frag_pos += len; 990 if (data->in_frag_pos > wpabuf_size(data->inbuf)) { 991 wpa_printf(MSG_INFO, "EAP-pwd: Buffer overflow attack " 992 "detected (%d vs. %d)!", 993 (int) data->in_frag_pos, 994 (int) wpabuf_len(data->inbuf)); 995 wpabuf_free(data->inbuf); 996 data->inbuf = NULL; 997 data->in_frag_pos = 0; 998 return NULL; 999 } 1000 wpabuf_put_data(data->inbuf, pos, len); 1001 } 1002 if (EAP_PWD_GET_MORE_BIT(lm_exch)) { 1003 resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, 1004 EAP_PWD_HDR_SIZE, 1005 EAP_CODE_RESPONSE, eap_get_id(reqData)); 1006 if (resp != NULL) 1007 wpabuf_put_u8(resp, (EAP_PWD_GET_EXCHANGE(lm_exch))); 1008 wpa_printf(MSG_DEBUG, "EAP-pwd: ACKing a %d byte fragment", 1009 (int) len); 1010 return resp; 1011 } 1012 /* 1013 * we're buffering and this is the last fragment 1014 */ 1015 if (data->in_frag_pos && data->inbuf) { 1016 wpa_printf(MSG_DEBUG, "EAP-pwd: Last fragment, %d bytes", 1017 (int) len); 1018 pos = wpabuf_head_u8(data->inbuf); 1019 len = data->in_frag_pos; 1020 } 1021 wpa_printf(MSG_DEBUG, "EAP-pwd: processing frame: exch %d, len %d", 1022 EAP_PWD_GET_EXCHANGE(lm_exch), (int) len); 1023 1024 switch (EAP_PWD_GET_EXCHANGE(lm_exch)) { 1025 case EAP_PWD_OPCODE_ID_EXCH: 1026 eap_pwd_perform_id_exchange(sm, data, ret, reqData, 1027 pos, len); 1028 break; 1029 case EAP_PWD_OPCODE_COMMIT_EXCH: 1030 eap_pwd_perform_commit_exchange(sm, data, ret, reqData, 1031 pos, len); 1032 break; 1033 case EAP_PWD_OPCODE_CONFIRM_EXCH: 1034 eap_pwd_perform_confirm_exchange(sm, data, ret, reqData, 1035 pos, len); 1036 break; 1037 default: 1038 wpa_printf(MSG_INFO, "EAP-pwd: Ignoring message with unknown " 1039 "opcode %d", lm_exch); 1040 break; 1041 } 1042 /* 1043 * if we buffered the just processed input now's the time to free it 1044 */ 1045 if (data->in_frag_pos) { 1046 wpabuf_free(data->inbuf); 1047 data->inbuf = NULL; 1048 data->in_frag_pos = 0; 1049 } 1050 1051 if (data->outbuf == NULL) { 1052 ret->methodState = METHOD_DONE; 1053 ret->decision = DECISION_FAIL; 1054 return NULL; /* generic failure */ 1055 } 1056 1057 /* 1058 * we have output! Do we need to fragment it? 1059 */ 1060 lm_exch = EAP_PWD_GET_EXCHANGE(lm_exch); 1061 len = wpabuf_len(data->outbuf); 1062 if ((len + EAP_PWD_HDR_SIZE) > data->mtu) { 1063 resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, data->mtu, 1064 EAP_CODE_RESPONSE, eap_get_id(reqData)); 1065 /* 1066 * if so it's the first so include a length field 1067 */ 1068 EAP_PWD_SET_LENGTH_BIT(lm_exch); 1069 EAP_PWD_SET_MORE_BIT(lm_exch); 1070 tot_len = len; 1071 /* 1072 * keep the packet at the MTU 1073 */ 1074 len = data->mtu - EAP_PWD_HDR_SIZE - sizeof(u16); 1075 wpa_printf(MSG_DEBUG, "EAP-pwd: Fragmenting output, total " 1076 "length = %d", tot_len); 1077 } else { 1078 resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, 1079 EAP_PWD_HDR_SIZE + len, 1080 EAP_CODE_RESPONSE, eap_get_id(reqData)); 1081 } 1082 if (resp == NULL) 1083 return NULL; 1084 1085 wpabuf_put_u8(resp, lm_exch); 1086 if (EAP_PWD_GET_LENGTH_BIT(lm_exch)) { 1087 wpabuf_put_be16(resp, tot_len); 1088 data->out_frag_pos += len; 1089 } 1090 buf = wpabuf_head_u8(data->outbuf); 1091 wpabuf_put_data(resp, buf, len); 1092 /* 1093 * if we're not fragmenting then there's no need to carry this around 1094 */ 1095 if (data->out_frag_pos == 0) { 1096 wpabuf_free(data->outbuf); 1097 data->outbuf = NULL; 1098 data->out_frag_pos = 0; 1099 if (data->state == SUCCESS_ON_FRAG_COMPLETION) { 1100 ret->methodState = METHOD_DONE; 1101 ret->decision = DECISION_UNCOND_SUCC; 1102 eap_pwd_state(data, SUCCESS); 1103 } 1104 } 1105 1106 return resp; 1107 } 1108 1109 1110 static Boolean eap_pwd_key_available(struct eap_sm *sm, void *priv) 1111 { 1112 struct eap_pwd_data *data = priv; 1113 return data->state == SUCCESS; 1114 } 1115 1116 1117 static u8 * eap_pwd_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 1118 { 1119 struct eap_pwd_data *data = priv; 1120 u8 *key; 1121 1122 if (data->state != SUCCESS) 1123 return NULL; 1124 1125 if ((key = os_malloc(EAP_EMSK_LEN)) == NULL) 1126 return NULL; 1127 1128 os_memcpy(key, data->emsk, EAP_EMSK_LEN); 1129 *len = EAP_EMSK_LEN; 1130 1131 return key; 1132 } 1133 1134 1135 int eap_peer_pwd_register(void) 1136 { 1137 struct eap_method *eap; 1138 1139 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 1140 EAP_VENDOR_IETF, EAP_TYPE_PWD, "PWD"); 1141 if (eap == NULL) 1142 return -1; 1143 1144 eap->init = eap_pwd_init; 1145 eap->deinit = eap_pwd_deinit; 1146 eap->process = eap_pwd_process; 1147 eap->isKeyAvailable = eap_pwd_key_available; 1148 eap->getKey = eap_pwd_getkey; 1149 eap->getSessionId = eap_pwd_get_session_id; 1150 eap->get_emsk = eap_pwd_get_emsk; 1151 1152 return eap_peer_method_register(eap); 1153 } 1154