1 /* 2 * Simultaneous authentication of equals 3 * Copyright (c) 2012-2016, Jouni Malinen <j@w1.fi> 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 "utils/const_time.h" 13 #include "crypto/crypto.h" 14 #include "crypto/sha256.h" 15 #include "crypto/sha384.h" 16 #include "crypto/sha512.h" 17 #include "crypto/random.h" 18 #include "crypto/dh_groups.h" 19 #include "ieee802_11_defs.h" 20 #include "dragonfly.h" 21 #include "sae.h" 22 23 24 int sae_set_group(struct sae_data *sae, int group) 25 { 26 struct sae_temporary_data *tmp; 27 28 #ifdef CONFIG_TESTING_OPTIONS 29 /* Allow all groups for testing purposes in non-production builds. */ 30 #else /* CONFIG_TESTING_OPTIONS */ 31 if (!dragonfly_suitable_group(group, 0)) { 32 wpa_printf(MSG_DEBUG, "SAE: Reject unsuitable group %d", group); 33 return -1; 34 } 35 #endif /* CONFIG_TESTING_OPTIONS */ 36 37 sae_clear_data(sae); 38 tmp = sae->tmp = os_zalloc(sizeof(*tmp)); 39 if (tmp == NULL) 40 return -1; 41 42 /* First, check if this is an ECC group */ 43 tmp->ec = crypto_ec_init(group); 44 if (tmp->ec) { 45 wpa_printf(MSG_DEBUG, "SAE: Selecting supported ECC group %d", 46 group); 47 sae->group = group; 48 tmp->prime_len = crypto_ec_prime_len(tmp->ec); 49 tmp->prime = crypto_ec_get_prime(tmp->ec); 50 tmp->order_len = crypto_ec_order_len(tmp->ec); 51 tmp->order = crypto_ec_get_order(tmp->ec); 52 return 0; 53 } 54 55 /* Not an ECC group, check FFC */ 56 tmp->dh = dh_groups_get(group); 57 if (tmp->dh) { 58 wpa_printf(MSG_DEBUG, "SAE: Selecting supported FFC group %d", 59 group); 60 sae->group = group; 61 tmp->prime_len = tmp->dh->prime_len; 62 if (tmp->prime_len > SAE_MAX_PRIME_LEN) { 63 sae_clear_data(sae); 64 return -1; 65 } 66 67 tmp->prime_buf = crypto_bignum_init_set(tmp->dh->prime, 68 tmp->prime_len); 69 if (tmp->prime_buf == NULL) { 70 sae_clear_data(sae); 71 return -1; 72 } 73 tmp->prime = tmp->prime_buf; 74 75 tmp->order_len = tmp->dh->order_len; 76 tmp->order_buf = crypto_bignum_init_set(tmp->dh->order, 77 tmp->dh->order_len); 78 if (tmp->order_buf == NULL) { 79 sae_clear_data(sae); 80 return -1; 81 } 82 tmp->order = tmp->order_buf; 83 84 return 0; 85 } 86 87 /* Unsupported group */ 88 wpa_printf(MSG_DEBUG, 89 "SAE: Group %d not supported by the crypto library", group); 90 return -1; 91 } 92 93 94 void sae_clear_temp_data(struct sae_data *sae) 95 { 96 struct sae_temporary_data *tmp; 97 if (sae == NULL || sae->tmp == NULL) 98 return; 99 tmp = sae->tmp; 100 crypto_ec_deinit(tmp->ec); 101 crypto_bignum_deinit(tmp->prime_buf, 0); 102 crypto_bignum_deinit(tmp->order_buf, 0); 103 crypto_bignum_deinit(tmp->sae_rand, 1); 104 crypto_bignum_deinit(tmp->pwe_ffc, 1); 105 crypto_bignum_deinit(tmp->own_commit_scalar, 0); 106 crypto_bignum_deinit(tmp->own_commit_element_ffc, 0); 107 crypto_bignum_deinit(tmp->peer_commit_element_ffc, 0); 108 crypto_ec_point_deinit(tmp->pwe_ecc, 1); 109 crypto_ec_point_deinit(tmp->own_commit_element_ecc, 0); 110 crypto_ec_point_deinit(tmp->peer_commit_element_ecc, 0); 111 wpabuf_free(tmp->anti_clogging_token); 112 wpabuf_free(tmp->own_rejected_groups); 113 wpabuf_free(tmp->peer_rejected_groups); 114 os_free(tmp->pw_id); 115 bin_clear_free(tmp, sizeof(*tmp)); 116 sae->tmp = NULL; 117 } 118 119 120 void sae_clear_data(struct sae_data *sae) 121 { 122 if (sae == NULL) 123 return; 124 sae_clear_temp_data(sae); 125 crypto_bignum_deinit(sae->peer_commit_scalar, 0); 126 crypto_bignum_deinit(sae->peer_commit_scalar_accepted, 0); 127 os_memset(sae, 0, sizeof(*sae)); 128 } 129 130 131 static void sae_pwd_seed_key(const u8 *addr1, const u8 *addr2, u8 *key) 132 { 133 wpa_printf(MSG_DEBUG, "SAE: PWE derivation - addr1=" MACSTR 134 " addr2=" MACSTR, MAC2STR(addr1), MAC2STR(addr2)); 135 if (os_memcmp(addr1, addr2, ETH_ALEN) > 0) { 136 os_memcpy(key, addr1, ETH_ALEN); 137 os_memcpy(key + ETH_ALEN, addr2, ETH_ALEN); 138 } else { 139 os_memcpy(key, addr2, ETH_ALEN); 140 os_memcpy(key + ETH_ALEN, addr1, ETH_ALEN); 141 } 142 } 143 144 145 static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed, 146 const u8 *prime, const u8 *qr, const u8 *qnr, 147 u8 *pwd_value) 148 { 149 struct crypto_bignum *y_sqr, *x_cand; 150 int res; 151 size_t bits; 152 int cmp_prime; 153 unsigned int in_range; 154 155 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN); 156 157 /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */ 158 bits = crypto_ec_prime_len_bits(sae->tmp->ec); 159 if (sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking", 160 prime, sae->tmp->prime_len, pwd_value, bits) < 0) 161 return -1; 162 if (bits % 8) 163 buf_shift_right(pwd_value, sae->tmp->prime_len, 8 - bits % 8); 164 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", 165 pwd_value, sae->tmp->prime_len); 166 167 cmp_prime = const_time_memcmp(pwd_value, prime, sae->tmp->prime_len); 168 /* Create a const_time mask for selection based on prf result 169 * being smaller than prime. */ 170 in_range = const_time_fill_msb((unsigned int) cmp_prime); 171 /* The algorithm description would skip the next steps if 172 * cmp_prime >= 0 (return 0 here), but go through them regardless to 173 * minimize externally observable differences in behavior. */ 174 175 x_cand = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len); 176 if (!x_cand) 177 return -1; 178 y_sqr = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x_cand); 179 crypto_bignum_deinit(x_cand, 1); 180 if (!y_sqr) 181 return -1; 182 183 res = dragonfly_is_quadratic_residue_blind(sae->tmp->ec, qr, qnr, 184 y_sqr); 185 crypto_bignum_deinit(y_sqr, 1); 186 if (res < 0) 187 return res; 188 return const_time_select_int(in_range, res, 0); 189 } 190 191 192 /* Returns -1 on fatal failure, 0 if PWE cannot be derived from the provided 193 * pwd-seed, or 1 if a valid PWE was derived from pwd-seed. */ 194 static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed, 195 struct crypto_bignum *pwe) 196 { 197 u8 pwd_value[SAE_MAX_PRIME_LEN]; 198 size_t bits = sae->tmp->prime_len * 8; 199 u8 exp[1]; 200 struct crypto_bignum *a, *b = NULL; 201 int res, is_val; 202 u8 pwd_value_valid; 203 204 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN); 205 206 /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */ 207 if (sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking", 208 sae->tmp->dh->prime, sae->tmp->prime_len, pwd_value, 209 bits) < 0) 210 return -1; 211 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", pwd_value, 212 sae->tmp->prime_len); 213 214 /* Check whether pwd-value < p */ 215 res = const_time_memcmp(pwd_value, sae->tmp->dh->prime, 216 sae->tmp->prime_len); 217 /* pwd-value >= p is invalid, so res is < 0 for the valid cases and 218 * the negative sign can be used to fill the mask for constant time 219 * selection */ 220 pwd_value_valid = const_time_fill_msb(res); 221 222 /* If pwd-value >= p, force pwd-value to be < p and perform the 223 * calculations anyway to hide timing difference. The derived PWE will 224 * be ignored in that case. */ 225 pwd_value[0] = const_time_select_u8(pwd_value_valid, pwd_value[0], 0); 226 227 /* PWE = pwd-value^((p-1)/r) modulo p */ 228 229 res = -1; 230 a = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len); 231 if (!a) 232 goto fail; 233 234 /* This is an optimization based on the used group that does not depend 235 * on the password in any way, so it is fine to use separate branches 236 * for this step without constant time operations. */ 237 if (sae->tmp->dh->safe_prime) { 238 /* 239 * r = (p-1)/2 for the group used here, so this becomes: 240 * PWE = pwd-value^2 modulo p 241 */ 242 exp[0] = 2; 243 b = crypto_bignum_init_set(exp, sizeof(exp)); 244 } else { 245 /* Calculate exponent: (p-1)/r */ 246 exp[0] = 1; 247 b = crypto_bignum_init_set(exp, sizeof(exp)); 248 if (b == NULL || 249 crypto_bignum_sub(sae->tmp->prime, b, b) < 0 || 250 crypto_bignum_div(b, sae->tmp->order, b) < 0) 251 goto fail; 252 } 253 254 if (!b) 255 goto fail; 256 257 res = crypto_bignum_exptmod(a, b, sae->tmp->prime, pwe); 258 if (res < 0) 259 goto fail; 260 261 /* There were no fatal errors in calculations, so determine the return 262 * value using constant time operations. We get here for number of 263 * invalid cases which are cleared here after having performed all the 264 * computation. PWE is valid if pwd-value was less than prime and 265 * PWE > 1. Start with pwd-value check first and then use constant time 266 * operations to clear res to 0 if PWE is 0 or 1. 267 */ 268 res = const_time_select_u8(pwd_value_valid, 1, 0); 269 is_val = crypto_bignum_is_zero(pwe); 270 res = const_time_select_u8(const_time_is_zero(is_val), res, 0); 271 is_val = crypto_bignum_is_one(pwe); 272 res = const_time_select_u8(const_time_is_zero(is_val), res, 0); 273 274 fail: 275 crypto_bignum_deinit(a, 1); 276 crypto_bignum_deinit(b, 1); 277 return res; 278 } 279 280 281 static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1, 282 const u8 *addr2, const u8 *password, 283 size_t password_len) 284 { 285 u8 counter, k; 286 u8 addrs[2 * ETH_ALEN]; 287 const u8 *addr[2]; 288 size_t len[2]; 289 u8 *dummy_password, *tmp_password; 290 int pwd_seed_odd = 0; 291 u8 prime[SAE_MAX_ECC_PRIME_LEN]; 292 size_t prime_len; 293 struct crypto_bignum *x = NULL, *qr = NULL, *qnr = NULL; 294 u8 x_bin[SAE_MAX_ECC_PRIME_LEN]; 295 u8 x_cand_bin[SAE_MAX_ECC_PRIME_LEN]; 296 u8 qr_bin[SAE_MAX_ECC_PRIME_LEN]; 297 u8 qnr_bin[SAE_MAX_ECC_PRIME_LEN]; 298 int res = -1; 299 u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_* 300 * mask */ 301 302 os_memset(x_bin, 0, sizeof(x_bin)); 303 304 dummy_password = os_malloc(password_len); 305 tmp_password = os_malloc(password_len); 306 if (!dummy_password || !tmp_password || 307 random_get_bytes(dummy_password, password_len) < 0) 308 goto fail; 309 310 prime_len = sae->tmp->prime_len; 311 if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime), 312 prime_len) < 0) 313 goto fail; 314 315 /* 316 * Create a random quadratic residue (qr) and quadratic non-residue 317 * (qnr) modulo p for blinding purposes during the loop. 318 */ 319 if (dragonfly_get_random_qr_qnr(sae->tmp->prime, &qr, &qnr) < 0 || 320 crypto_bignum_to_bin(qr, qr_bin, sizeof(qr_bin), prime_len) < 0 || 321 crypto_bignum_to_bin(qnr, qnr_bin, sizeof(qnr_bin), prime_len) < 0) 322 goto fail; 323 324 wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password", 325 password, password_len); 326 327 /* 328 * H(salt, ikm) = HMAC-SHA256(salt, ikm) 329 * base = password 330 * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC), 331 * base || counter) 332 */ 333 sae_pwd_seed_key(addr1, addr2, addrs); 334 335 addr[0] = tmp_password; 336 len[0] = password_len; 337 addr[1] = &counter; 338 len[1] = sizeof(counter); 339 340 /* 341 * Continue for at least k iterations to protect against side-channel 342 * attacks that attempt to determine the number of iterations required 343 * in the loop. 344 */ 345 k = dragonfly_min_pwe_loop_iter(sae->group); 346 347 for (counter = 1; counter <= k || !found; counter++) { 348 u8 pwd_seed[SHA256_MAC_LEN]; 349 350 if (counter > 200) { 351 /* This should not happen in practice */ 352 wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE"); 353 break; 354 } 355 356 wpa_printf(MSG_DEBUG, "SAE: counter = %03u", counter); 357 const_time_select_bin(found, dummy_password, password, 358 password_len, tmp_password); 359 if (hmac_sha256_vector(addrs, sizeof(addrs), 2, 360 addr, len, pwd_seed) < 0) 361 break; 362 363 res = sae_test_pwd_seed_ecc(sae, pwd_seed, 364 prime, qr_bin, qnr_bin, x_cand_bin); 365 const_time_select_bin(found, x_bin, x_cand_bin, prime_len, 366 x_bin); 367 pwd_seed_odd = const_time_select_u8( 368 found, pwd_seed_odd, 369 pwd_seed[SHA256_MAC_LEN - 1] & 0x01); 370 os_memset(pwd_seed, 0, sizeof(pwd_seed)); 371 if (res < 0) 372 goto fail; 373 /* Need to minimize differences in handling res == 0 and 1 here 374 * to avoid differences in timing and instruction cache access, 375 * so use const_time_select_*() to make local copies of the 376 * values based on whether this loop iteration was the one that 377 * found the pwd-seed/x. */ 378 379 /* found is 0 or 0xff here and res is 0 or 1. Bitwise OR of them 380 * (with res converted to 0/0xff) handles this in constant time. 381 */ 382 found |= res * 0xff; 383 wpa_printf(MSG_DEBUG, "SAE: pwd-seed result %d found=0x%02x", 384 res, found); 385 } 386 387 if (!found) { 388 wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE"); 389 res = -1; 390 goto fail; 391 } 392 393 x = crypto_bignum_init_set(x_bin, prime_len); 394 if (!x) { 395 res = -1; 396 goto fail; 397 } 398 399 if (!sae->tmp->pwe_ecc) 400 sae->tmp->pwe_ecc = crypto_ec_point_init(sae->tmp->ec); 401 if (!sae->tmp->pwe_ecc) 402 res = -1; 403 else 404 res = crypto_ec_point_solve_y_coord(sae->tmp->ec, 405 sae->tmp->pwe_ecc, x, 406 pwd_seed_odd); 407 if (res < 0) { 408 /* 409 * This should not happen since we already checked that there 410 * is a result. 411 */ 412 wpa_printf(MSG_DEBUG, "SAE: Could not solve y"); 413 } 414 415 fail: 416 crypto_bignum_deinit(qr, 0); 417 crypto_bignum_deinit(qnr, 0); 418 os_free(dummy_password); 419 bin_clear_free(tmp_password, password_len); 420 crypto_bignum_deinit(x, 1); 421 os_memset(x_bin, 0, sizeof(x_bin)); 422 os_memset(x_cand_bin, 0, sizeof(x_cand_bin)); 423 424 return res; 425 } 426 427 428 static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1, 429 const u8 *addr2, const u8 *password, 430 size_t password_len) 431 { 432 u8 counter, k, sel_counter = 0; 433 u8 addrs[2 * ETH_ALEN]; 434 const u8 *addr[2]; 435 size_t len[2]; 436 u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_* 437 * mask */ 438 u8 mask; 439 struct crypto_bignum *pwe; 440 size_t prime_len = sae->tmp->prime_len * 8; 441 u8 *pwe_buf; 442 443 crypto_bignum_deinit(sae->tmp->pwe_ffc, 1); 444 sae->tmp->pwe_ffc = NULL; 445 446 /* Allocate a buffer to maintain selected and candidate PWE for constant 447 * time selection. */ 448 pwe_buf = os_zalloc(prime_len * 2); 449 pwe = crypto_bignum_init(); 450 if (!pwe_buf || !pwe) 451 goto fail; 452 453 wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password", 454 password, password_len); 455 456 /* 457 * H(salt, ikm) = HMAC-SHA256(salt, ikm) 458 * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC), 459 * password || counter) 460 */ 461 sae_pwd_seed_key(addr1, addr2, addrs); 462 463 addr[0] = password; 464 len[0] = password_len; 465 addr[1] = &counter; 466 len[1] = sizeof(counter); 467 468 k = dragonfly_min_pwe_loop_iter(sae->group); 469 470 for (counter = 1; counter <= k || !found; counter++) { 471 u8 pwd_seed[SHA256_MAC_LEN]; 472 int res; 473 474 if (counter > 200) { 475 /* This should not happen in practice */ 476 wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE"); 477 break; 478 } 479 480 wpa_printf(MSG_DEBUG, "SAE: counter = %02u", counter); 481 if (hmac_sha256_vector(addrs, sizeof(addrs), 2, 482 addr, len, pwd_seed) < 0) 483 break; 484 res = sae_test_pwd_seed_ffc(sae, pwd_seed, pwe); 485 /* res is -1 for fatal failure, 0 if a valid PWE was not found, 486 * or 1 if a valid PWE was found. */ 487 if (res < 0) 488 break; 489 /* Store the candidate PWE into the second half of pwe_buf and 490 * the selected PWE in the beginning of pwe_buf using constant 491 * time selection. */ 492 if (crypto_bignum_to_bin(pwe, pwe_buf + prime_len, prime_len, 493 prime_len) < 0) 494 break; 495 const_time_select_bin(found, pwe_buf, pwe_buf + prime_len, 496 prime_len, pwe_buf); 497 sel_counter = const_time_select_u8(found, sel_counter, counter); 498 mask = const_time_eq_u8(res, 1); 499 found = const_time_select_u8(found, found, mask); 500 } 501 502 if (!found) 503 goto fail; 504 505 wpa_printf(MSG_DEBUG, "SAE: Use PWE from counter = %02u", sel_counter); 506 sae->tmp->pwe_ffc = crypto_bignum_init_set(pwe_buf, prime_len); 507 fail: 508 crypto_bignum_deinit(pwe, 1); 509 bin_clear_free(pwe_buf, prime_len * 2); 510 return sae->tmp->pwe_ffc ? 0 : -1; 511 } 512 513 514 static int hkdf_extract(size_t hash_len, const u8 *salt, size_t salt_len, 515 size_t num_elem, const u8 *addr[], const size_t len[], 516 u8 *prk) 517 { 518 if (hash_len == 32) 519 return hmac_sha256_vector(salt, salt_len, num_elem, addr, len, 520 prk); 521 #ifdef CONFIG_SHA384 522 if (hash_len == 48) 523 return hmac_sha384_vector(salt, salt_len, num_elem, addr, len, 524 prk); 525 #endif /* CONFIG_SHA384 */ 526 #ifdef CONFIG_SHA512 527 if (hash_len == 64) 528 return hmac_sha512_vector(salt, salt_len, num_elem, addr, len, 529 prk); 530 #endif /* CONFIG_SHA512 */ 531 return -1; 532 } 533 534 535 static int hkdf_expand(size_t hash_len, const u8 *prk, size_t prk_len, 536 const char *info, u8 *okm, size_t okm_len) 537 { 538 size_t info_len = os_strlen(info); 539 540 if (hash_len == 32) 541 return hmac_sha256_kdf(prk, prk_len, NULL, 542 (const u8 *) info, info_len, 543 okm, okm_len); 544 #ifdef CONFIG_SHA384 545 if (hash_len == 48) 546 return hmac_sha384_kdf(prk, prk_len, NULL, 547 (const u8 *) info, info_len, 548 okm, okm_len); 549 #endif /* CONFIG_SHA384 */ 550 #ifdef CONFIG_SHA512 551 if (hash_len == 64) 552 return hmac_sha512_kdf(prk, prk_len, NULL, 553 (const u8 *) info, info_len, 554 okm, okm_len); 555 #endif /* CONFIG_SHA512 */ 556 return -1; 557 } 558 559 560 static int sswu_curve_param(int group, int *z) 561 { 562 switch (group) { 563 case 19: 564 *z = -10; 565 return 0; 566 case 20: 567 *z = -12; 568 return 0; 569 case 21: 570 *z = -4; 571 return 0; 572 case 25: 573 case 29: 574 *z = -5; 575 return 0; 576 case 26: 577 *z = 31; 578 return 0; 579 case 28: 580 *z = -2; 581 return 0; 582 case 30: 583 *z = 7; 584 return 0; 585 } 586 587 return -1; 588 } 589 590 591 static void debug_print_bignum(const char *title, const struct crypto_bignum *a, 592 size_t prime_len) 593 { 594 u8 *bin; 595 596 bin = os_malloc(prime_len); 597 if (bin && crypto_bignum_to_bin(a, bin, prime_len, prime_len) >= 0) 598 wpa_hexdump_key(MSG_DEBUG, title, bin, prime_len); 599 else 600 wpa_printf(MSG_DEBUG, "Could not print bignum (%s)", title); 601 bin_clear_free(bin, prime_len); 602 } 603 604 605 static struct crypto_ec_point * sswu(struct crypto_ec *ec, int group, 606 const struct crypto_bignum *u) 607 { 608 int z_int; 609 const struct crypto_bignum *a, *b, *prime; 610 struct crypto_bignum *u2, *t1, *t2, *z, *t, *zero, *one, *two, *three, 611 *x1a, *x1b, *y = NULL; 612 struct crypto_bignum *x1 = NULL, *x2, *gx1, *gx2, *v = NULL; 613 unsigned int m_is_zero, is_qr, is_eq; 614 size_t prime_len; 615 u8 bin[SAE_MAX_ECC_PRIME_LEN]; 616 u8 bin1[SAE_MAX_ECC_PRIME_LEN]; 617 u8 bin2[SAE_MAX_ECC_PRIME_LEN]; 618 u8 x_y[2 * SAE_MAX_ECC_PRIME_LEN]; 619 struct crypto_ec_point *p = NULL; 620 621 if (sswu_curve_param(group, &z_int) < 0) 622 return NULL; 623 624 prime = crypto_ec_get_prime(ec); 625 prime_len = crypto_ec_prime_len(ec); 626 a = crypto_ec_get_a(ec); 627 b = crypto_ec_get_b(ec); 628 629 u2 = crypto_bignum_init(); 630 t1 = crypto_bignum_init(); 631 t2 = crypto_bignum_init(); 632 z = crypto_bignum_init_uint(abs(z_int)); 633 t = crypto_bignum_init(); 634 zero = crypto_bignum_init_uint(0); 635 one = crypto_bignum_init_uint(1); 636 two = crypto_bignum_init_uint(2); 637 three = crypto_bignum_init_uint(3); 638 x1a = crypto_bignum_init(); 639 x1b = crypto_bignum_init(); 640 x2 = crypto_bignum_init(); 641 gx1 = crypto_bignum_init(); 642 gx2 = crypto_bignum_init(); 643 if (!u2 || !t1 || !t2 || !z || !t || !zero || !one || !two || !three || 644 !x1a || !x1b || !x2 || !gx1 || !gx2) 645 goto fail; 646 647 if (z_int < 0 && crypto_bignum_sub(prime, z, z) < 0) 648 goto fail; 649 650 /* m = z^2 * u^4 + z * u^2 */ 651 /* --> tmp = z * u^2, m = tmp^2 + tmp */ 652 653 /* u2 = u^2 654 * t1 = z * u2 655 * t2 = t1^2 656 * m = t1 = t1 + t2 */ 657 if (crypto_bignum_sqrmod(u, prime, u2) < 0 || 658 crypto_bignum_mulmod(z, u2, prime, t1) < 0 || 659 crypto_bignum_sqrmod(t1, prime, t2) < 0 || 660 crypto_bignum_addmod(t1, t2, prime, t1) < 0) 661 goto fail; 662 debug_print_bignum("SSWU: m", t1, prime_len); 663 664 /* l = CEQ(m, 0) 665 * t = CSEL(l, 0, inverse(m); where inverse(x) is calculated as 666 * x^(p-2) modulo p which will handle m == 0 case correctly */ 667 /* TODO: Make sure crypto_bignum_is_zero() is constant time */ 668 m_is_zero = const_time_eq(crypto_bignum_is_zero(t1), 1); 669 /* t = m^(p-2) modulo p */ 670 if (crypto_bignum_sub(prime, two, t2) < 0 || 671 crypto_bignum_exptmod(t1, t2, prime, t) < 0) 672 goto fail; 673 debug_print_bignum("SSWU: t", t, prime_len); 674 675 /* b / (z * a) */ 676 if (crypto_bignum_mulmod(z, a, prime, t1) < 0 || 677 crypto_bignum_inverse(t1, prime, t1) < 0 || 678 crypto_bignum_mulmod(b, t1, prime, x1a) < 0) 679 goto fail; 680 debug_print_bignum("SSWU: x1a = b / (z * a)", x1a, prime_len); 681 682 /* (-b/a) * (1 + t) */ 683 if (crypto_bignum_sub(prime, b, t1) < 0 || 684 crypto_bignum_inverse(a, prime, t2) < 0 || 685 crypto_bignum_mulmod(t1, t2, prime, t1) < 0 || 686 crypto_bignum_addmod(one, t, prime, t2) < 0 || 687 crypto_bignum_mulmod(t1, t2, prime, x1b) < 0) 688 goto fail; 689 debug_print_bignum("SSWU: x1b = (-b/a) * (1 + t)", x1b, prime_len); 690 691 /* x1 = CSEL(CEQ(m, 0), x1a, x1b) */ 692 if (crypto_bignum_to_bin(x1a, bin1, sizeof(bin1), prime_len) < 0 || 693 crypto_bignum_to_bin(x1b, bin2, sizeof(bin2), prime_len) < 0) 694 goto fail; 695 const_time_select_bin(m_is_zero, bin1, bin2, prime_len, bin); 696 x1 = crypto_bignum_init_set(bin, prime_len); 697 if (!x1) 698 goto fail; 699 debug_print_bignum("SSWU: x1 = CSEL(l, x1a, x1b)", x1, prime_len); 700 701 /* gx1 = x1^3 + a * x1 + b */ 702 if (crypto_bignum_exptmod(x1, three, prime, t1) < 0 || 703 crypto_bignum_mulmod(a, x1, prime, t2) < 0 || 704 crypto_bignum_addmod(t1, t2, prime, t1) < 0 || 705 crypto_bignum_addmod(t1, b, prime, gx1) < 0) 706 goto fail; 707 debug_print_bignum("SSWU: gx1 = x1^3 + a * x1 + b", gx1, prime_len); 708 709 /* x2 = z * u^2 * x1 */ 710 if (crypto_bignum_mulmod(z, u2, prime, t1) < 0 || 711 crypto_bignum_mulmod(t1, x1, prime, x2) < 0) 712 goto fail; 713 debug_print_bignum("SSWU: x2 = z * u^2 * x1", x2, prime_len); 714 715 /* gx2 = x2^3 + a * x2 + b */ 716 if (crypto_bignum_exptmod(x2, three, prime, t1) < 0 || 717 crypto_bignum_mulmod(a, x2, prime, t2) < 0 || 718 crypto_bignum_addmod(t1, t2, prime, t1) < 0 || 719 crypto_bignum_addmod(t1, b, prime, gx2) < 0) 720 goto fail; 721 debug_print_bignum("SSWU: gx2 = x2^3 + a * x2 + b", gx2, prime_len); 722 723 /* l = gx1 is a quadratic residue modulo p 724 * --> gx1^((p-1)/2) modulo p is zero or one */ 725 if (crypto_bignum_sub(prime, one, t1) < 0 || 726 crypto_bignum_rshift(t1, 1, t1) < 0 || 727 crypto_bignum_exptmod(gx1, t1, prime, t1) < 0) 728 goto fail; 729 debug_print_bignum("SSWU: gx1^((p-1)/2) modulo p", t1, prime_len); 730 is_qr = const_time_eq(crypto_bignum_is_zero(t1) | 731 crypto_bignum_is_one(t1), 1); 732 733 /* v = CSEL(l, gx1, gx2) */ 734 if (crypto_bignum_to_bin(gx1, bin1, sizeof(bin1), prime_len) < 0 || 735 crypto_bignum_to_bin(gx2, bin2, sizeof(bin2), prime_len) < 0) 736 goto fail; 737 const_time_select_bin(is_qr, bin1, bin2, prime_len, bin); 738 v = crypto_bignum_init_set(bin, prime_len); 739 if (!v) 740 goto fail; 741 debug_print_bignum("SSWU: v = CSEL(l, gx1, gx2)", v, prime_len); 742 743 /* x = CSEL(l, x1, x2) */ 744 if (crypto_bignum_to_bin(x1, bin1, sizeof(bin1), prime_len) < 0 || 745 crypto_bignum_to_bin(x2, bin2, sizeof(bin2), prime_len) < 0) 746 goto fail; 747 const_time_select_bin(is_qr, bin1, bin2, prime_len, x_y); 748 wpa_hexdump_key(MSG_DEBUG, "SSWU: x = CSEL(l, x1, x2)", x_y, prime_len); 749 750 /* y = sqrt(v) 751 * For prime p such that p = 3 mod 4 --> v^((p+1)/4) */ 752 if (crypto_bignum_to_bin(prime, bin1, sizeof(bin1), prime_len) < 0) 753 goto fail; 754 if ((bin1[prime_len - 1] & 0x03) != 3) { 755 wpa_printf(MSG_DEBUG, "SSWU: prime does not have p = 3 mod 4"); 756 goto fail; 757 } 758 y = crypto_bignum_init(); 759 if (!y || 760 crypto_bignum_add(prime, one, t1) < 0 || 761 crypto_bignum_rshift(t1, 2, t1) < 0 || 762 crypto_bignum_exptmod(v, t1, prime, y) < 0) 763 goto fail; 764 debug_print_bignum("SSWU: y = sqrt(v)", y, prime_len); 765 766 /* l = CEQ(LSB(u), LSB(y)) */ 767 if (crypto_bignum_to_bin(u, bin1, sizeof(bin1), prime_len) < 0 || 768 crypto_bignum_to_bin(y, bin2, sizeof(bin2), prime_len) < 0) 769 goto fail; 770 is_eq = const_time_eq(bin1[prime_len - 1] & 0x01, 771 bin2[prime_len - 1] & 0x01); 772 773 /* P = CSEL(l, (x,y), (x, p-y)) */ 774 if (crypto_bignum_sub(prime, y, t1) < 0) 775 goto fail; 776 debug_print_bignum("SSWU: p - y", t1, prime_len); 777 if (crypto_bignum_to_bin(y, bin1, sizeof(bin1), prime_len) < 0 || 778 crypto_bignum_to_bin(t1, bin2, sizeof(bin2), prime_len) < 0) 779 goto fail; 780 const_time_select_bin(is_eq, bin1, bin2, prime_len, &x_y[prime_len]); 781 782 /* output P */ 783 wpa_hexdump_key(MSG_DEBUG, "SSWU: P.x", x_y, prime_len); 784 wpa_hexdump_key(MSG_DEBUG, "SSWU: P.y", &x_y[prime_len], prime_len); 785 p = crypto_ec_point_from_bin(ec, x_y); 786 787 fail: 788 crypto_bignum_deinit(u2, 1); 789 crypto_bignum_deinit(t1, 1); 790 crypto_bignum_deinit(t2, 1); 791 crypto_bignum_deinit(z, 0); 792 crypto_bignum_deinit(t, 1); 793 crypto_bignum_deinit(x1a, 1); 794 crypto_bignum_deinit(x1b, 1); 795 crypto_bignum_deinit(x1, 1); 796 crypto_bignum_deinit(x2, 1); 797 crypto_bignum_deinit(gx1, 1); 798 crypto_bignum_deinit(gx2, 1); 799 crypto_bignum_deinit(y, 1); 800 crypto_bignum_deinit(v, 1); 801 crypto_bignum_deinit(zero, 0); 802 crypto_bignum_deinit(one, 0); 803 crypto_bignum_deinit(two, 0); 804 crypto_bignum_deinit(three, 0); 805 forced_memzero(bin, sizeof(bin)); 806 forced_memzero(bin1, sizeof(bin1)); 807 forced_memzero(bin2, sizeof(bin2)); 808 forced_memzero(x_y, sizeof(x_y)); 809 return p; 810 } 811 812 813 static int sae_pwd_seed(size_t hash_len, const u8 *ssid, size_t ssid_len, 814 const u8 *password, size_t password_len, 815 const char *identifier, u8 *pwd_seed) 816 { 817 const u8 *addr[2]; 818 size_t len[2]; 819 size_t num_elem; 820 821 /* pwd-seed = HKDF-Extract(ssid, password [ || identifier ]) */ 822 addr[0] = password; 823 len[0] = password_len; 824 num_elem = 1; 825 wpa_hexdump_ascii(MSG_DEBUG, "SAE: SSID", ssid, ssid_len); 826 wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password", 827 password, password_len); 828 if (identifier) { 829 wpa_printf(MSG_DEBUG, "SAE: password identifier: %s", 830 identifier); 831 addr[num_elem] = (const u8 *) identifier; 832 len[num_elem] = os_strlen(identifier); 833 num_elem++; 834 } 835 if (hkdf_extract(hash_len, ssid, ssid_len, num_elem, addr, len, 836 pwd_seed) < 0) 837 return -1; 838 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, hash_len); 839 return 0; 840 } 841 842 843 size_t sae_ecc_prime_len_2_hash_len(size_t prime_len) 844 { 845 if (prime_len <= 256 / 8) 846 return 32; 847 if (prime_len <= 384 / 8) 848 return 48; 849 return 64; 850 } 851 852 853 static struct crypto_ec_point * 854 sae_derive_pt_ecc(struct crypto_ec *ec, int group, 855 const u8 *ssid, size_t ssid_len, 856 const u8 *password, size_t password_len, 857 const char *identifier) 858 { 859 u8 pwd_seed[64]; 860 u8 pwd_value[SAE_MAX_ECC_PRIME_LEN * 2]; 861 size_t pwd_value_len, hash_len, prime_len; 862 const struct crypto_bignum *prime; 863 struct crypto_bignum *bn = NULL; 864 struct crypto_ec_point *p1 = NULL, *p2 = NULL, *pt = NULL; 865 866 prime = crypto_ec_get_prime(ec); 867 prime_len = crypto_ec_prime_len(ec); 868 if (prime_len > SAE_MAX_ECC_PRIME_LEN) 869 goto fail; 870 hash_len = sae_ecc_prime_len_2_hash_len(prime_len); 871 872 /* len = olen(p) + ceil(olen(p)/2) */ 873 pwd_value_len = prime_len + (prime_len + 1) / 2; 874 875 if (sae_pwd_seed(hash_len, ssid, ssid_len, password, password_len, 876 identifier, pwd_seed) < 0) 877 goto fail; 878 879 /* pwd-value = HKDF-Expand(pwd-seed, "SAE Hash to Element u1 P1", len) 880 */ 881 if (hkdf_expand(hash_len, pwd_seed, hash_len, 882 "SAE Hash to Element u1 P1", pwd_value, pwd_value_len) < 883 0) 884 goto fail; 885 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value (u1 P1)", 886 pwd_value, pwd_value_len); 887 888 /* u1 = pwd-value modulo p */ 889 bn = crypto_bignum_init_set(pwd_value, pwd_value_len); 890 if (!bn || crypto_bignum_mod(bn, prime, bn) < 0 || 891 crypto_bignum_to_bin(bn, pwd_value, sizeof(pwd_value), 892 prime_len) < 0) 893 goto fail; 894 wpa_hexdump_key(MSG_DEBUG, "SAE: u1", pwd_value, prime_len); 895 896 /* P1 = SSWU(u1) */ 897 p1 = sswu(ec, group, bn); 898 if (!p1) 899 goto fail; 900 901 /* pwd-value = HKDF-Expand(pwd-seed, "SAE Hash to Element u2 P2", len) 902 */ 903 if (hkdf_expand(hash_len, pwd_seed, hash_len, 904 "SAE Hash to Element u2 P2", pwd_value, 905 pwd_value_len) < 0) 906 goto fail; 907 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value (u2 P2)", 908 pwd_value, pwd_value_len); 909 910 /* u2 = pwd-value modulo p */ 911 crypto_bignum_deinit(bn, 1); 912 bn = crypto_bignum_init_set(pwd_value, pwd_value_len); 913 if (!bn || crypto_bignum_mod(bn, prime, bn) < 0 || 914 crypto_bignum_to_bin(bn, pwd_value, sizeof(pwd_value), 915 prime_len) < 0) 916 goto fail; 917 wpa_hexdump_key(MSG_DEBUG, "SAE: u2", pwd_value, prime_len); 918 919 /* P2 = SSWU(u2) */ 920 p2 = sswu(ec, group, bn); 921 if (!p2) 922 goto fail; 923 924 /* PT = elem-op(P1, P2) */ 925 pt = crypto_ec_point_init(ec); 926 if (!pt) 927 goto fail; 928 if (crypto_ec_point_add(ec, p1, p2, pt) < 0) { 929 crypto_ec_point_deinit(pt, 1); 930 pt = NULL; 931 } 932 933 fail: 934 forced_memzero(pwd_seed, sizeof(pwd_seed)); 935 forced_memzero(pwd_value, sizeof(pwd_value)); 936 crypto_bignum_deinit(bn, 1); 937 crypto_ec_point_deinit(p1, 1); 938 crypto_ec_point_deinit(p2, 1); 939 return pt; 940 } 941 942 943 size_t sae_ffc_prime_len_2_hash_len(size_t prime_len) 944 { 945 if (prime_len <= 2048 / 8) 946 return 32; 947 if (prime_len <= 3072 / 8) 948 return 48; 949 return 64; 950 } 951 952 953 static struct crypto_bignum * 954 sae_derive_pt_ffc(const struct dh_group *dh, int group, 955 const u8 *ssid, size_t ssid_len, 956 const u8 *password, size_t password_len, 957 const char *identifier) 958 { 959 size_t hash_len, prime_len, pwd_value_len; 960 struct crypto_bignum *prime, *order; 961 struct crypto_bignum *one = NULL, *two = NULL, *bn = NULL, *tmp = NULL, 962 *pt = NULL; 963 u8 pwd_seed[64]; 964 u8 pwd_value[SAE_MAX_PRIME_LEN + SAE_MAX_PRIME_LEN / 2]; 965 966 prime = crypto_bignum_init_set(dh->prime, dh->prime_len); 967 order = crypto_bignum_init_set(dh->order, dh->order_len); 968 if (!prime || !order) 969 goto fail; 970 prime_len = dh->prime_len; 971 if (prime_len > SAE_MAX_PRIME_LEN) 972 goto fail; 973 hash_len = sae_ffc_prime_len_2_hash_len(prime_len); 974 975 /* len = olen(p) + ceil(olen(p)/2) */ 976 pwd_value_len = prime_len + (prime_len + 1) / 2; 977 if (pwd_value_len > sizeof(pwd_value)) 978 goto fail; 979 980 if (sae_pwd_seed(hash_len, ssid, ssid_len, password, password_len, 981 identifier, pwd_seed) < 0) 982 goto fail; 983 984 /* pwd-value = HKDF-Expand(pwd-seed, "SAE Hash to Element", len) */ 985 if (hkdf_expand(hash_len, pwd_seed, hash_len, 986 "SAE Hash to Element", pwd_value, pwd_value_len) < 0) 987 goto fail; 988 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", 989 pwd_value, pwd_value_len); 990 991 /* pwd-value = (pwd-value modulo (p-2)) + 2 */ 992 bn = crypto_bignum_init_set(pwd_value, pwd_value_len); 993 one = crypto_bignum_init_uint(1); 994 two = crypto_bignum_init_uint(2); 995 tmp = crypto_bignum_init(); 996 if (!bn || !one || !two || !tmp || 997 crypto_bignum_sub(prime, two, tmp) < 0 || 998 crypto_bignum_mod(bn, tmp, bn) < 0 || 999 crypto_bignum_add(bn, two, bn) < 0 || 1000 crypto_bignum_to_bin(bn, pwd_value, sizeof(pwd_value), 1001 prime_len) < 0) 1002 goto fail; 1003 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value(reduced)", 1004 pwd_value, prime_len); 1005 1006 /* PT = pwd-value^((p-1)/q) modulo p */ 1007 pt = crypto_bignum_init(); 1008 if (!pt || 1009 crypto_bignum_sub(prime, one, tmp) < 0 || 1010 crypto_bignum_div(tmp, order, tmp) < 0 || 1011 crypto_bignum_exptmod(bn, tmp, prime, pt) < 0) { 1012 crypto_bignum_deinit(pt, 1); 1013 pt = NULL; 1014 goto fail; 1015 } 1016 debug_print_bignum("SAE: PT", pt, prime_len); 1017 1018 fail: 1019 forced_memzero(pwd_seed, sizeof(pwd_seed)); 1020 forced_memzero(pwd_value, sizeof(pwd_value)); 1021 crypto_bignum_deinit(bn, 1); 1022 crypto_bignum_deinit(tmp, 1); 1023 crypto_bignum_deinit(one, 0); 1024 crypto_bignum_deinit(two, 0); 1025 crypto_bignum_deinit(prime, 0); 1026 crypto_bignum_deinit(order, 0); 1027 return pt; 1028 } 1029 1030 1031 static struct sae_pt * 1032 sae_derive_pt_group(int group, const u8 *ssid, size_t ssid_len, 1033 const u8 *password, size_t password_len, 1034 const char *identifier) 1035 { 1036 struct sae_pt *pt; 1037 1038 wpa_printf(MSG_DEBUG, "SAE: Derive PT - group %d", group); 1039 1040 if (ssid_len > 32) 1041 return NULL; 1042 1043 pt = os_zalloc(sizeof(*pt)); 1044 if (!pt) 1045 return NULL; 1046 1047 #ifdef CONFIG_SAE_PK 1048 os_memcpy(pt->ssid, ssid, ssid_len); 1049 pt->ssid_len = ssid_len; 1050 #endif /* CONFIG_SAE_PK */ 1051 pt->group = group; 1052 pt->ec = crypto_ec_init(group); 1053 if (pt->ec) { 1054 pt->ecc_pt = sae_derive_pt_ecc(pt->ec, group, ssid, ssid_len, 1055 password, password_len, 1056 identifier); 1057 if (!pt->ecc_pt) { 1058 wpa_printf(MSG_DEBUG, "SAE: Failed to derive PT"); 1059 goto fail; 1060 } 1061 1062 return pt; 1063 } 1064 1065 pt->dh = dh_groups_get(group); 1066 if (!pt->dh) { 1067 wpa_printf(MSG_DEBUG, "SAE: Unsupported group %d", group); 1068 goto fail; 1069 } 1070 1071 pt->ffc_pt = sae_derive_pt_ffc(pt->dh, group, ssid, ssid_len, 1072 password, password_len, identifier); 1073 if (!pt->ffc_pt) { 1074 wpa_printf(MSG_DEBUG, "SAE: Failed to derive PT"); 1075 goto fail; 1076 } 1077 1078 return pt; 1079 fail: 1080 sae_deinit_pt(pt); 1081 return NULL; 1082 } 1083 1084 1085 struct sae_pt * sae_derive_pt(int *groups, const u8 *ssid, size_t ssid_len, 1086 const u8 *password, size_t password_len, 1087 const char *identifier) 1088 { 1089 struct sae_pt *pt = NULL, *last = NULL, *tmp; 1090 int default_groups[] = { 19, 0 }; 1091 int i; 1092 1093 if (!groups) 1094 groups = default_groups; 1095 for (i = 0; groups[i] > 0; i++) { 1096 tmp = sae_derive_pt_group(groups[i], ssid, ssid_len, password, 1097 password_len, identifier); 1098 if (!tmp) 1099 continue; 1100 1101 if (last) 1102 last->next = tmp; 1103 else 1104 pt = tmp; 1105 last = tmp; 1106 } 1107 1108 return pt; 1109 } 1110 1111 1112 static void sae_max_min_addr(const u8 *addr[], size_t len[], 1113 const u8 *addr1, const u8 *addr2) 1114 { 1115 len[0] = ETH_ALEN; 1116 len[1] = ETH_ALEN; 1117 if (os_memcmp(addr1, addr2, ETH_ALEN) > 0) { 1118 addr[0] = addr1; 1119 addr[1] = addr2; 1120 } else { 1121 addr[0] = addr2; 1122 addr[1] = addr1; 1123 } 1124 } 1125 1126 1127 struct crypto_ec_point * 1128 sae_derive_pwe_from_pt_ecc(const struct sae_pt *pt, 1129 const u8 *addr1, const u8 *addr2) 1130 { 1131 u8 bin[SAE_MAX_ECC_PRIME_LEN * 2]; 1132 size_t prime_len; 1133 const u8 *addr[2]; 1134 size_t len[2]; 1135 u8 salt[64], hash[64]; 1136 size_t hash_len; 1137 const struct crypto_bignum *order; 1138 struct crypto_bignum *tmp = NULL, *val = NULL, *one = NULL; 1139 struct crypto_ec_point *pwe = NULL; 1140 1141 wpa_printf(MSG_DEBUG, "SAE: Derive PWE from PT"); 1142 prime_len = crypto_ec_prime_len(pt->ec); 1143 if (crypto_ec_point_to_bin(pt->ec, pt->ecc_pt, 1144 bin, bin + prime_len) < 0) 1145 return NULL; 1146 wpa_hexdump_key(MSG_DEBUG, "SAE: PT.x", bin, prime_len); 1147 wpa_hexdump_key(MSG_DEBUG, "SAE: PT.y", bin + prime_len, prime_len); 1148 1149 sae_max_min_addr(addr, len, addr1, addr2); 1150 1151 /* val = H(0^n, 1152 * MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC)) */ 1153 wpa_printf(MSG_DEBUG, "SAE: val = H(0^n, MAX(addrs) || MIN(addrs))"); 1154 hash_len = sae_ecc_prime_len_2_hash_len(prime_len); 1155 os_memset(salt, 0, hash_len); 1156 if (hkdf_extract(hash_len, salt, hash_len, 2, addr, len, hash) < 0) 1157 goto fail; 1158 wpa_hexdump(MSG_DEBUG, "SAE: val", hash, hash_len); 1159 1160 /* val = val modulo (q - 1) + 1 */ 1161 order = crypto_ec_get_order(pt->ec); 1162 tmp = crypto_bignum_init(); 1163 val = crypto_bignum_init_set(hash, hash_len); 1164 one = crypto_bignum_init_uint(1); 1165 if (!tmp || !val || !one || 1166 crypto_bignum_sub(order, one, tmp) < 0 || 1167 crypto_bignum_mod(val, tmp, val) < 0 || 1168 crypto_bignum_add(val, one, val) < 0) 1169 goto fail; 1170 debug_print_bignum("SAE: val(reduced to 1..q-1)", val, prime_len); 1171 1172 /* PWE = scalar-op(val, PT) */ 1173 pwe = crypto_ec_point_init(pt->ec); 1174 if (!pwe || 1175 crypto_ec_point_mul(pt->ec, pt->ecc_pt, val, pwe) < 0 || 1176 crypto_ec_point_to_bin(pt->ec, pwe, bin, bin + prime_len) < 0) { 1177 crypto_ec_point_deinit(pwe, 1); 1178 pwe = NULL; 1179 goto fail; 1180 } 1181 wpa_hexdump_key(MSG_DEBUG, "SAE: PWE.x", bin, prime_len); 1182 wpa_hexdump_key(MSG_DEBUG, "SAE: PWE.y", bin + prime_len, prime_len); 1183 1184 fail: 1185 crypto_bignum_deinit(tmp, 1); 1186 crypto_bignum_deinit(val, 1); 1187 crypto_bignum_deinit(one, 0); 1188 return pwe; 1189 } 1190 1191 1192 struct crypto_bignum * 1193 sae_derive_pwe_from_pt_ffc(const struct sae_pt *pt, 1194 const u8 *addr1, const u8 *addr2) 1195 { 1196 size_t prime_len; 1197 const u8 *addr[2]; 1198 size_t len[2]; 1199 u8 salt[64], hash[64]; 1200 size_t hash_len; 1201 struct crypto_bignum *tmp = NULL, *val = NULL, *one = NULL; 1202 struct crypto_bignum *pwe = NULL, *order = NULL, *prime = NULL; 1203 1204 wpa_printf(MSG_DEBUG, "SAE: Derive PWE from PT"); 1205 prime = crypto_bignum_init_set(pt->dh->prime, pt->dh->prime_len); 1206 order = crypto_bignum_init_set(pt->dh->order, pt->dh->order_len); 1207 if (!prime || !order) 1208 goto fail; 1209 prime_len = pt->dh->prime_len; 1210 1211 sae_max_min_addr(addr, len, addr1, addr2); 1212 1213 /* val = H(0^n, 1214 * MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC)) */ 1215 wpa_printf(MSG_DEBUG, "SAE: val = H(0^n, MAX(addrs) || MIN(addrs))"); 1216 hash_len = sae_ffc_prime_len_2_hash_len(prime_len); 1217 os_memset(salt, 0, hash_len); 1218 if (hkdf_extract(hash_len, salt, hash_len, 2, addr, len, hash) < 0) 1219 goto fail; 1220 wpa_hexdump(MSG_DEBUG, "SAE: val", hash, hash_len); 1221 1222 /* val = val modulo (q - 1) + 1 */ 1223 tmp = crypto_bignum_init(); 1224 val = crypto_bignum_init_set(hash, hash_len); 1225 one = crypto_bignum_init_uint(1); 1226 if (!tmp || !val || !one || 1227 crypto_bignum_sub(order, one, tmp) < 0 || 1228 crypto_bignum_mod(val, tmp, val) < 0 || 1229 crypto_bignum_add(val, one, val) < 0) 1230 goto fail; 1231 debug_print_bignum("SAE: val(reduced to 1..q-1)", val, prime_len); 1232 1233 /* PWE = scalar-op(val, PT) */ 1234 pwe = crypto_bignum_init(); 1235 if (!pwe || crypto_bignum_exptmod(pt->ffc_pt, val, prime, pwe) < 0) { 1236 crypto_bignum_deinit(pwe, 1); 1237 pwe = NULL; 1238 goto fail; 1239 } 1240 debug_print_bignum("SAE: PWE", pwe, prime_len); 1241 1242 fail: 1243 crypto_bignum_deinit(tmp, 1); 1244 crypto_bignum_deinit(val, 1); 1245 crypto_bignum_deinit(one, 0); 1246 crypto_bignum_deinit(prime, 0); 1247 crypto_bignum_deinit(order, 0); 1248 return pwe; 1249 } 1250 1251 1252 void sae_deinit_pt(struct sae_pt *pt) 1253 { 1254 struct sae_pt *prev; 1255 1256 while (pt) { 1257 crypto_ec_point_deinit(pt->ecc_pt, 1); 1258 crypto_bignum_deinit(pt->ffc_pt, 1); 1259 crypto_ec_deinit(pt->ec); 1260 prev = pt; 1261 pt = pt->next; 1262 os_free(prev); 1263 } 1264 } 1265 1266 1267 static int sae_derive_commit_element_ecc(struct sae_data *sae, 1268 struct crypto_bignum *mask) 1269 { 1270 /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */ 1271 if (!sae->tmp->own_commit_element_ecc) { 1272 sae->tmp->own_commit_element_ecc = 1273 crypto_ec_point_init(sae->tmp->ec); 1274 if (!sae->tmp->own_commit_element_ecc) 1275 return -1; 1276 } 1277 1278 if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc, mask, 1279 sae->tmp->own_commit_element_ecc) < 0 || 1280 crypto_ec_point_invert(sae->tmp->ec, 1281 sae->tmp->own_commit_element_ecc) < 0) { 1282 wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element"); 1283 return -1; 1284 } 1285 1286 return 0; 1287 } 1288 1289 1290 static int sae_derive_commit_element_ffc(struct sae_data *sae, 1291 struct crypto_bignum *mask) 1292 { 1293 /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */ 1294 if (!sae->tmp->own_commit_element_ffc) { 1295 sae->tmp->own_commit_element_ffc = crypto_bignum_init(); 1296 if (!sae->tmp->own_commit_element_ffc) 1297 return -1; 1298 } 1299 1300 if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, mask, sae->tmp->prime, 1301 sae->tmp->own_commit_element_ffc) < 0 || 1302 crypto_bignum_inverse(sae->tmp->own_commit_element_ffc, 1303 sae->tmp->prime, 1304 sae->tmp->own_commit_element_ffc) < 0) { 1305 wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element"); 1306 return -1; 1307 } 1308 1309 return 0; 1310 } 1311 1312 1313 static int sae_derive_commit(struct sae_data *sae) 1314 { 1315 struct crypto_bignum *mask; 1316 int ret; 1317 1318 mask = crypto_bignum_init(); 1319 if (!sae->tmp->sae_rand) 1320 sae->tmp->sae_rand = crypto_bignum_init(); 1321 if (!sae->tmp->own_commit_scalar) 1322 sae->tmp->own_commit_scalar = crypto_bignum_init(); 1323 ret = !mask || !sae->tmp->sae_rand || !sae->tmp->own_commit_scalar || 1324 dragonfly_generate_scalar(sae->tmp->order, sae->tmp->sae_rand, 1325 mask, 1326 sae->tmp->own_commit_scalar) < 0 || 1327 (sae->tmp->ec && 1328 sae_derive_commit_element_ecc(sae, mask) < 0) || 1329 (sae->tmp->dh && 1330 sae_derive_commit_element_ffc(sae, mask) < 0); 1331 crypto_bignum_deinit(mask, 1); 1332 return ret ? -1 : 0; 1333 } 1334 1335 1336 int sae_prepare_commit(const u8 *addr1, const u8 *addr2, 1337 const u8 *password, size_t password_len, 1338 struct sae_data *sae) 1339 { 1340 if (sae->tmp == NULL || 1341 (sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password, 1342 password_len) < 0) || 1343 (sae->tmp->dh && sae_derive_pwe_ffc(sae, addr1, addr2, password, 1344 password_len) < 0)) 1345 return -1; 1346 1347 sae->h2e = 0; 1348 sae->pk = 0; 1349 return sae_derive_commit(sae); 1350 } 1351 1352 1353 int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt, 1354 const u8 *addr1, const u8 *addr2, 1355 int *rejected_groups, const struct sae_pk *pk) 1356 { 1357 if (!sae->tmp) 1358 return -1; 1359 1360 while (pt) { 1361 if (pt->group == sae->group) 1362 break; 1363 pt = pt->next; 1364 } 1365 if (!pt) { 1366 wpa_printf(MSG_INFO, "SAE: Could not find PT for group %u", 1367 sae->group); 1368 return -1; 1369 } 1370 1371 #ifdef CONFIG_SAE_PK 1372 os_memcpy(sae->tmp->ssid, pt->ssid, pt->ssid_len); 1373 sae->tmp->ssid_len = pt->ssid_len; 1374 sae->tmp->ap_pk = pk; 1375 #endif /* CONFIG_SAE_PK */ 1376 sae->tmp->own_addr_higher = os_memcmp(addr1, addr2, ETH_ALEN) > 0; 1377 wpabuf_free(sae->tmp->own_rejected_groups); 1378 sae->tmp->own_rejected_groups = NULL; 1379 if (rejected_groups) { 1380 int count, i; 1381 struct wpabuf *groups; 1382 1383 count = int_array_len(rejected_groups); 1384 groups = wpabuf_alloc(count * 2); 1385 if (!groups) 1386 return -1; 1387 for (i = 0; i < count; i++) 1388 wpabuf_put_le16(groups, rejected_groups[i]); 1389 sae->tmp->own_rejected_groups = groups; 1390 } 1391 1392 if (pt->ec) { 1393 crypto_ec_point_deinit(sae->tmp->pwe_ecc, 1); 1394 sae->tmp->pwe_ecc = sae_derive_pwe_from_pt_ecc(pt, addr1, 1395 addr2); 1396 if (!sae->tmp->pwe_ecc) 1397 return -1; 1398 } 1399 1400 if (pt->dh) { 1401 crypto_bignum_deinit(sae->tmp->pwe_ffc, 1); 1402 sae->tmp->pwe_ffc = sae_derive_pwe_from_pt_ffc(pt, addr1, 1403 addr2); 1404 if (!sae->tmp->pwe_ffc) 1405 return -1; 1406 } 1407 1408 sae->h2e = 1; 1409 return sae_derive_commit(sae); 1410 } 1411 1412 1413 static int sae_derive_k_ecc(struct sae_data *sae, u8 *k) 1414 { 1415 struct crypto_ec_point *K; 1416 int ret = -1; 1417 1418 K = crypto_ec_point_init(sae->tmp->ec); 1419 if (K == NULL) 1420 goto fail; 1421 1422 /* 1423 * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE), 1424 * PEER-COMMIT-ELEMENT))) 1425 * If K is identity element (point-at-infinity), reject 1426 * k = F(K) (= x coordinate) 1427 */ 1428 1429 if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc, 1430 sae->peer_commit_scalar, K) < 0 || 1431 crypto_ec_point_add(sae->tmp->ec, K, 1432 sae->tmp->peer_commit_element_ecc, K) < 0 || 1433 crypto_ec_point_mul(sae->tmp->ec, K, sae->tmp->sae_rand, K) < 0 || 1434 crypto_ec_point_is_at_infinity(sae->tmp->ec, K) || 1435 crypto_ec_point_to_bin(sae->tmp->ec, K, k, NULL) < 0) { 1436 wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k"); 1437 goto fail; 1438 } 1439 1440 wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len); 1441 1442 ret = 0; 1443 fail: 1444 crypto_ec_point_deinit(K, 1); 1445 return ret; 1446 } 1447 1448 1449 static int sae_derive_k_ffc(struct sae_data *sae, u8 *k) 1450 { 1451 struct crypto_bignum *K; 1452 int ret = -1; 1453 1454 K = crypto_bignum_init(); 1455 if (K == NULL) 1456 goto fail; 1457 1458 /* 1459 * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE), 1460 * PEER-COMMIT-ELEMENT))) 1461 * If K is identity element (one), reject. 1462 * k = F(K) (= x coordinate) 1463 */ 1464 1465 if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, sae->peer_commit_scalar, 1466 sae->tmp->prime, K) < 0 || 1467 crypto_bignum_mulmod(K, sae->tmp->peer_commit_element_ffc, 1468 sae->tmp->prime, K) < 0 || 1469 crypto_bignum_exptmod(K, sae->tmp->sae_rand, sae->tmp->prime, K) < 0 1470 || 1471 crypto_bignum_is_one(K) || 1472 crypto_bignum_to_bin(K, k, SAE_MAX_PRIME_LEN, sae->tmp->prime_len) < 1473 0) { 1474 wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k"); 1475 goto fail; 1476 } 1477 1478 wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len); 1479 1480 ret = 0; 1481 fail: 1482 crypto_bignum_deinit(K, 1); 1483 return ret; 1484 } 1485 1486 1487 static int sae_kdf_hash(size_t hash_len, const u8 *k, const char *label, 1488 const u8 *context, size_t context_len, 1489 u8 *out, size_t out_len) 1490 { 1491 if (hash_len == 32) 1492 return sha256_prf(k, hash_len, label, 1493 context, context_len, out, out_len); 1494 #ifdef CONFIG_SHA384 1495 if (hash_len == 48) 1496 return sha384_prf(k, hash_len, label, 1497 context, context_len, out, out_len); 1498 #endif /* CONFIG_SHA384 */ 1499 #ifdef CONFIG_SHA512 1500 if (hash_len == 64) 1501 return sha512_prf(k, hash_len, label, 1502 context, context_len, out, out_len); 1503 #endif /* CONFIG_SHA512 */ 1504 return -1; 1505 } 1506 1507 1508 static int sae_derive_keys(struct sae_data *sae, const u8 *k) 1509 { 1510 u8 zero[SAE_MAX_HASH_LEN], val[SAE_MAX_PRIME_LEN]; 1511 const u8 *salt; 1512 struct wpabuf *rejected_groups = NULL; 1513 u8 keyseed[SAE_MAX_HASH_LEN]; 1514 u8 keys[2 * SAE_MAX_HASH_LEN + SAE_PMK_LEN]; 1515 struct crypto_bignum *tmp; 1516 int ret = -1; 1517 size_t hash_len, salt_len, prime_len = sae->tmp->prime_len; 1518 const u8 *addr[1]; 1519 size_t len[1]; 1520 1521 tmp = crypto_bignum_init(); 1522 if (tmp == NULL) 1523 goto fail; 1524 1525 /* keyseed = H(salt, k) 1526 * KCK || PMK = KDF-Hash-Length(keyseed, "SAE KCK and PMK", 1527 * (commit-scalar + peer-commit-scalar) modulo r) 1528 * PMKID = L((commit-scalar + peer-commit-scalar) modulo r, 0, 128) 1529 * 1530 * When SAE-PK is used, 1531 * KCK || PMK || KEK = KDF-Hash-Length(keyseed, "SAE-PK keys", context) 1532 */ 1533 if (!sae->h2e) 1534 hash_len = SHA256_MAC_LEN; 1535 else if (sae->tmp->dh) 1536 hash_len = sae_ffc_prime_len_2_hash_len(prime_len); 1537 else 1538 hash_len = sae_ecc_prime_len_2_hash_len(prime_len); 1539 if (sae->h2e && (sae->tmp->own_rejected_groups || 1540 sae->tmp->peer_rejected_groups)) { 1541 struct wpabuf *own, *peer; 1542 1543 own = sae->tmp->own_rejected_groups; 1544 peer = sae->tmp->peer_rejected_groups; 1545 salt_len = 0; 1546 if (own) 1547 salt_len += wpabuf_len(own); 1548 if (peer) 1549 salt_len += wpabuf_len(peer); 1550 rejected_groups = wpabuf_alloc(salt_len); 1551 if (!rejected_groups) 1552 goto fail; 1553 if (sae->tmp->own_addr_higher) { 1554 if (own) 1555 wpabuf_put_buf(rejected_groups, own); 1556 if (peer) 1557 wpabuf_put_buf(rejected_groups, peer); 1558 } else { 1559 if (peer) 1560 wpabuf_put_buf(rejected_groups, peer); 1561 if (own) 1562 wpabuf_put_buf(rejected_groups, own); 1563 } 1564 salt = wpabuf_head(rejected_groups); 1565 salt_len = wpabuf_len(rejected_groups); 1566 } else { 1567 os_memset(zero, 0, hash_len); 1568 salt = zero; 1569 salt_len = hash_len; 1570 } 1571 wpa_hexdump(MSG_DEBUG, "SAE: salt for keyseed derivation", 1572 salt, salt_len); 1573 addr[0] = k; 1574 len[0] = prime_len; 1575 if (hkdf_extract(hash_len, salt, salt_len, 1, addr, len, keyseed) < 0) 1576 goto fail; 1577 wpa_hexdump_key(MSG_DEBUG, "SAE: keyseed", keyseed, hash_len); 1578 1579 if (crypto_bignum_add(sae->tmp->own_commit_scalar, 1580 sae->peer_commit_scalar, tmp) < 0 || 1581 crypto_bignum_mod(tmp, sae->tmp->order, tmp) < 0) 1582 goto fail; 1583 /* IEEE Std 802.11-2016 is not exactly clear on the encoding of the bit 1584 * string that is needed for KCK, PMK, and PMKID derivation, but it 1585 * seems to make most sense to encode the 1586 * (commit-scalar + peer-commit-scalar) mod r part as a bit string by 1587 * zero padding it from left to the length of the order (in full 1588 * octets). */ 1589 crypto_bignum_to_bin(tmp, val, sizeof(val), sae->tmp->order_len); 1590 wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN); 1591 1592 #ifdef CONFIG_SAE_PK 1593 if (sae->pk) { 1594 if (sae_kdf_hash(hash_len, keyseed, "SAE-PK keys", 1595 val, sae->tmp->order_len, 1596 keys, 2 * hash_len + SAE_PMK_LEN) < 0) 1597 goto fail; 1598 } else { 1599 if (sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK", 1600 val, sae->tmp->order_len, 1601 keys, hash_len + SAE_PMK_LEN) < 0) 1602 goto fail; 1603 } 1604 #else /* CONFIG_SAE_PK */ 1605 if (sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK", 1606 val, sae->tmp->order_len, 1607 keys, hash_len + SAE_PMK_LEN) < 0) 1608 goto fail; 1609 #endif /* !CONFIG_SAE_PK */ 1610 1611 forced_memzero(keyseed, sizeof(keyseed)); 1612 os_memcpy(sae->tmp->kck, keys, hash_len); 1613 sae->tmp->kck_len = hash_len; 1614 os_memcpy(sae->pmk, keys + hash_len, SAE_PMK_LEN); 1615 os_memcpy(sae->pmkid, val, SAE_PMKID_LEN); 1616 #ifdef CONFIG_SAE_PK 1617 if (sae->pk) { 1618 os_memcpy(sae->tmp->kek, keys + hash_len + SAE_PMK_LEN, 1619 hash_len); 1620 sae->tmp->kek_len = hash_len; 1621 wpa_hexdump_key(MSG_DEBUG, "SAE: KEK for SAE-PK", 1622 sae->tmp->kek, sae->tmp->kek_len); 1623 } 1624 #endif /* CONFIG_SAE_PK */ 1625 forced_memzero(keys, sizeof(keys)); 1626 wpa_hexdump_key(MSG_DEBUG, "SAE: KCK", 1627 sae->tmp->kck, sae->tmp->kck_len); 1628 wpa_hexdump_key(MSG_DEBUG, "SAE: PMK", sae->pmk, SAE_PMK_LEN); 1629 1630 ret = 0; 1631 fail: 1632 wpabuf_free(rejected_groups); 1633 crypto_bignum_deinit(tmp, 0); 1634 return ret; 1635 } 1636 1637 1638 int sae_process_commit(struct sae_data *sae) 1639 { 1640 u8 k[SAE_MAX_PRIME_LEN]; 1641 if (sae->tmp == NULL || 1642 (sae->tmp->ec && sae_derive_k_ecc(sae, k) < 0) || 1643 (sae->tmp->dh && sae_derive_k_ffc(sae, k) < 0) || 1644 sae_derive_keys(sae, k) < 0) 1645 return -1; 1646 return 0; 1647 } 1648 1649 1650 int sae_write_commit(struct sae_data *sae, struct wpabuf *buf, 1651 const struct wpabuf *token, const char *identifier) 1652 { 1653 u8 *pos; 1654 1655 if (sae->tmp == NULL) 1656 return -1; 1657 1658 wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */ 1659 if (!sae->h2e && token) { 1660 wpabuf_put_buf(buf, token); 1661 wpa_hexdump(MSG_DEBUG, "SAE: Anti-clogging token", 1662 wpabuf_head(token), wpabuf_len(token)); 1663 } 1664 pos = wpabuf_put(buf, sae->tmp->prime_len); 1665 if (crypto_bignum_to_bin(sae->tmp->own_commit_scalar, pos, 1666 sae->tmp->prime_len, sae->tmp->prime_len) < 0) 1667 return -1; 1668 wpa_hexdump(MSG_DEBUG, "SAE: own commit-scalar", 1669 pos, sae->tmp->prime_len); 1670 if (sae->tmp->ec) { 1671 pos = wpabuf_put(buf, 2 * sae->tmp->prime_len); 1672 if (crypto_ec_point_to_bin(sae->tmp->ec, 1673 sae->tmp->own_commit_element_ecc, 1674 pos, pos + sae->tmp->prime_len) < 0) 1675 return -1; 1676 wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(x)", 1677 pos, sae->tmp->prime_len); 1678 wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(y)", 1679 pos + sae->tmp->prime_len, sae->tmp->prime_len); 1680 } else { 1681 pos = wpabuf_put(buf, sae->tmp->prime_len); 1682 if (crypto_bignum_to_bin(sae->tmp->own_commit_element_ffc, pos, 1683 sae->tmp->prime_len, 1684 sae->tmp->prime_len) < 0) 1685 return -1; 1686 wpa_hexdump(MSG_DEBUG, "SAE: own commit-element", 1687 pos, sae->tmp->prime_len); 1688 } 1689 1690 if (identifier) { 1691 /* Password Identifier element */ 1692 wpabuf_put_u8(buf, WLAN_EID_EXTENSION); 1693 wpabuf_put_u8(buf, 1 + os_strlen(identifier)); 1694 wpabuf_put_u8(buf, WLAN_EID_EXT_PASSWORD_IDENTIFIER); 1695 wpabuf_put_str(buf, identifier); 1696 wpa_printf(MSG_DEBUG, "SAE: own Password Identifier: %s", 1697 identifier); 1698 } 1699 1700 if (sae->h2e && sae->tmp->own_rejected_groups) { 1701 wpa_hexdump_buf(MSG_DEBUG, "SAE: own Rejected Groups", 1702 sae->tmp->own_rejected_groups); 1703 wpabuf_put_u8(buf, WLAN_EID_EXTENSION); 1704 wpabuf_put_u8(buf, 1705 1 + wpabuf_len(sae->tmp->own_rejected_groups)); 1706 wpabuf_put_u8(buf, WLAN_EID_EXT_REJECTED_GROUPS); 1707 wpabuf_put_buf(buf, sae->tmp->own_rejected_groups); 1708 } 1709 1710 if (sae->h2e && token) { 1711 wpabuf_put_u8(buf, WLAN_EID_EXTENSION); 1712 wpabuf_put_u8(buf, 1 + wpabuf_len(token)); 1713 wpabuf_put_u8(buf, WLAN_EID_EXT_ANTI_CLOGGING_TOKEN); 1714 wpabuf_put_buf(buf, token); 1715 wpa_hexdump_buf(MSG_DEBUG, 1716 "SAE: Anti-clogging token (in container)", 1717 token); 1718 } 1719 1720 return 0; 1721 } 1722 1723 1724 u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group) 1725 { 1726 if (allowed_groups) { 1727 int i; 1728 for (i = 0; allowed_groups[i] > 0; i++) { 1729 if (allowed_groups[i] == group) 1730 break; 1731 } 1732 if (allowed_groups[i] != group) { 1733 wpa_printf(MSG_DEBUG, "SAE: Proposed group %u not " 1734 "enabled in the current configuration", 1735 group); 1736 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; 1737 } 1738 } 1739 1740 if (sae->state == SAE_COMMITTED && group != sae->group) { 1741 wpa_printf(MSG_DEBUG, "SAE: Do not allow group to be changed"); 1742 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; 1743 } 1744 1745 if (group != sae->group && sae_set_group(sae, group) < 0) { 1746 wpa_printf(MSG_DEBUG, "SAE: Unsupported Finite Cyclic Group %u", 1747 group); 1748 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; 1749 } 1750 1751 if (sae->tmp == NULL) { 1752 wpa_printf(MSG_DEBUG, "SAE: Group information not yet initialized"); 1753 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1754 } 1755 1756 if (sae->tmp->dh && !allowed_groups) { 1757 wpa_printf(MSG_DEBUG, "SAE: Do not allow FFC group %u without " 1758 "explicit configuration enabling it", group); 1759 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; 1760 } 1761 1762 return WLAN_STATUS_SUCCESS; 1763 } 1764 1765 1766 static int sae_is_password_id_elem(const u8 *pos, const u8 *end) 1767 { 1768 return end - pos >= 3 && 1769 pos[0] == WLAN_EID_EXTENSION && 1770 pos[1] >= 1 && 1771 end - pos - 2 >= pos[1] && 1772 pos[2] == WLAN_EID_EXT_PASSWORD_IDENTIFIER; 1773 } 1774 1775 1776 static int sae_is_rejected_groups_elem(const u8 *pos, const u8 *end) 1777 { 1778 return end - pos >= 3 && 1779 pos[0] == WLAN_EID_EXTENSION && 1780 pos[1] >= 2 && 1781 end - pos - 2 >= pos[1] && 1782 pos[2] == WLAN_EID_EXT_REJECTED_GROUPS; 1783 } 1784 1785 1786 static int sae_is_token_container_elem(const u8 *pos, const u8 *end) 1787 { 1788 return end - pos >= 3 && 1789 pos[0] == WLAN_EID_EXTENSION && 1790 pos[1] >= 1 && 1791 end - pos - 2 >= pos[1] && 1792 pos[2] == WLAN_EID_EXT_ANTI_CLOGGING_TOKEN; 1793 } 1794 1795 1796 static void sae_parse_commit_token(struct sae_data *sae, const u8 **pos, 1797 const u8 *end, const u8 **token, 1798 size_t *token_len, int h2e) 1799 { 1800 size_t scalar_elem_len, tlen; 1801 1802 if (token) 1803 *token = NULL; 1804 if (token_len) 1805 *token_len = 0; 1806 1807 if (h2e) 1808 return; /* No Anti-Clogging Token field outside container IE */ 1809 1810 scalar_elem_len = (sae->tmp->ec ? 3 : 2) * sae->tmp->prime_len; 1811 if (scalar_elem_len >= (size_t) (end - *pos)) 1812 return; /* No extra data beyond peer scalar and element */ 1813 1814 tlen = end - (*pos + scalar_elem_len); 1815 1816 if (tlen < SHA256_MAC_LEN) { 1817 wpa_printf(MSG_DEBUG, 1818 "SAE: Too short optional data (%u octets) to include our Anti-Clogging Token", 1819 (unsigned int) tlen); 1820 return; 1821 } 1822 1823 wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token", *pos, tlen); 1824 if (token) 1825 *token = *pos; 1826 if (token_len) 1827 *token_len = tlen; 1828 *pos += tlen; 1829 } 1830 1831 1832 static void sae_parse_token_container(struct sae_data *sae, 1833 const u8 *pos, const u8 *end, 1834 const u8 **token, size_t *token_len) 1835 { 1836 wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame", 1837 pos, end - pos); 1838 if (!sae_is_token_container_elem(pos, end)) 1839 return; 1840 *token = pos + 3; 1841 *token_len = pos[1] - 1; 1842 wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token (in container)", 1843 *token, *token_len); 1844 } 1845 1846 1847 static u16 sae_parse_commit_scalar(struct sae_data *sae, const u8 **pos, 1848 const u8 *end) 1849 { 1850 struct crypto_bignum *peer_scalar; 1851 1852 if (sae->tmp->prime_len > end - *pos) { 1853 wpa_printf(MSG_DEBUG, "SAE: Not enough data for scalar"); 1854 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1855 } 1856 1857 peer_scalar = crypto_bignum_init_set(*pos, sae->tmp->prime_len); 1858 if (peer_scalar == NULL) 1859 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1860 1861 /* 1862 * IEEE Std 802.11-2012, 11.3.8.6.1: If there is a protocol instance for 1863 * the peer and it is in Authenticated state, the new Commit Message 1864 * shall be dropped if the peer-scalar is identical to the one used in 1865 * the existing protocol instance. 1866 */ 1867 if (sae->state == SAE_ACCEPTED && sae->peer_commit_scalar_accepted && 1868 crypto_bignum_cmp(sae->peer_commit_scalar_accepted, 1869 peer_scalar) == 0) { 1870 wpa_printf(MSG_DEBUG, "SAE: Do not accept re-use of previous " 1871 "peer-commit-scalar"); 1872 crypto_bignum_deinit(peer_scalar, 0); 1873 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1874 } 1875 1876 /* 1 < scalar < r */ 1877 if (crypto_bignum_is_zero(peer_scalar) || 1878 crypto_bignum_is_one(peer_scalar) || 1879 crypto_bignum_cmp(peer_scalar, sae->tmp->order) >= 0) { 1880 wpa_printf(MSG_DEBUG, "SAE: Invalid peer scalar"); 1881 crypto_bignum_deinit(peer_scalar, 0); 1882 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1883 } 1884 1885 1886 crypto_bignum_deinit(sae->peer_commit_scalar, 0); 1887 sae->peer_commit_scalar = peer_scalar; 1888 wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-scalar", 1889 *pos, sae->tmp->prime_len); 1890 *pos += sae->tmp->prime_len; 1891 1892 return WLAN_STATUS_SUCCESS; 1893 } 1894 1895 1896 static u16 sae_parse_commit_element_ecc(struct sae_data *sae, const u8 **pos, 1897 const u8 *end) 1898 { 1899 u8 prime[SAE_MAX_ECC_PRIME_LEN]; 1900 1901 if (2 * sae->tmp->prime_len > end - *pos) { 1902 wpa_printf(MSG_DEBUG, "SAE: Not enough data for " 1903 "commit-element"); 1904 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1905 } 1906 1907 if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime), 1908 sae->tmp->prime_len) < 0) 1909 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1910 1911 /* element x and y coordinates < p */ 1912 if (os_memcmp(*pos, prime, sae->tmp->prime_len) >= 0 || 1913 os_memcmp(*pos + sae->tmp->prime_len, prime, 1914 sae->tmp->prime_len) >= 0) { 1915 wpa_printf(MSG_DEBUG, "SAE: Invalid coordinates in peer " 1916 "element"); 1917 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1918 } 1919 1920 wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(x)", 1921 *pos, sae->tmp->prime_len); 1922 wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(y)", 1923 *pos + sae->tmp->prime_len, sae->tmp->prime_len); 1924 1925 crypto_ec_point_deinit(sae->tmp->peer_commit_element_ecc, 0); 1926 sae->tmp->peer_commit_element_ecc = 1927 crypto_ec_point_from_bin(sae->tmp->ec, *pos); 1928 if (sae->tmp->peer_commit_element_ecc == NULL) 1929 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1930 1931 if (!crypto_ec_point_is_on_curve(sae->tmp->ec, 1932 sae->tmp->peer_commit_element_ecc)) { 1933 wpa_printf(MSG_DEBUG, "SAE: Peer element is not on curve"); 1934 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1935 } 1936 1937 *pos += 2 * sae->tmp->prime_len; 1938 1939 return WLAN_STATUS_SUCCESS; 1940 } 1941 1942 1943 static u16 sae_parse_commit_element_ffc(struct sae_data *sae, const u8 **pos, 1944 const u8 *end) 1945 { 1946 struct crypto_bignum *res, *one; 1947 const u8 one_bin[1] = { 0x01 }; 1948 1949 if (sae->tmp->prime_len > end - *pos) { 1950 wpa_printf(MSG_DEBUG, "SAE: Not enough data for " 1951 "commit-element"); 1952 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1953 } 1954 wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element", *pos, 1955 sae->tmp->prime_len); 1956 1957 crypto_bignum_deinit(sae->tmp->peer_commit_element_ffc, 0); 1958 sae->tmp->peer_commit_element_ffc = 1959 crypto_bignum_init_set(*pos, sae->tmp->prime_len); 1960 if (sae->tmp->peer_commit_element_ffc == NULL) 1961 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1962 /* 1 < element < p - 1 */ 1963 res = crypto_bignum_init(); 1964 one = crypto_bignum_init_set(one_bin, sizeof(one_bin)); 1965 if (!res || !one || 1966 crypto_bignum_sub(sae->tmp->prime, one, res) || 1967 crypto_bignum_is_zero(sae->tmp->peer_commit_element_ffc) || 1968 crypto_bignum_is_one(sae->tmp->peer_commit_element_ffc) || 1969 crypto_bignum_cmp(sae->tmp->peer_commit_element_ffc, res) >= 0) { 1970 crypto_bignum_deinit(res, 0); 1971 crypto_bignum_deinit(one, 0); 1972 wpa_printf(MSG_DEBUG, "SAE: Invalid peer element"); 1973 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1974 } 1975 crypto_bignum_deinit(one, 0); 1976 1977 /* scalar-op(r, ELEMENT) = 1 modulo p */ 1978 if (crypto_bignum_exptmod(sae->tmp->peer_commit_element_ffc, 1979 sae->tmp->order, sae->tmp->prime, res) < 0 || 1980 !crypto_bignum_is_one(res)) { 1981 wpa_printf(MSG_DEBUG, "SAE: Invalid peer element (scalar-op)"); 1982 crypto_bignum_deinit(res, 0); 1983 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1984 } 1985 crypto_bignum_deinit(res, 0); 1986 1987 *pos += sae->tmp->prime_len; 1988 1989 return WLAN_STATUS_SUCCESS; 1990 } 1991 1992 1993 static u16 sae_parse_commit_element(struct sae_data *sae, const u8 **pos, 1994 const u8 *end) 1995 { 1996 if (sae->tmp->dh) 1997 return sae_parse_commit_element_ffc(sae, pos, end); 1998 return sae_parse_commit_element_ecc(sae, pos, end); 1999 } 2000 2001 2002 static int sae_parse_password_identifier(struct sae_data *sae, 2003 const u8 **pos, const u8 *end) 2004 { 2005 const u8 *epos; 2006 u8 len; 2007 2008 wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame", 2009 *pos, end - *pos); 2010 if (!sae_is_password_id_elem(*pos, end)) { 2011 if (sae->tmp->pw_id) { 2012 wpa_printf(MSG_DEBUG, 2013 "SAE: No Password Identifier included, but expected one (%s)", 2014 sae->tmp->pw_id); 2015 return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER; 2016 } 2017 os_free(sae->tmp->pw_id); 2018 sae->tmp->pw_id = NULL; 2019 return WLAN_STATUS_SUCCESS; /* No Password Identifier */ 2020 } 2021 2022 epos = *pos; 2023 epos++; /* skip IE type */ 2024 len = *epos++; /* IE length */ 2025 if (len > end - epos || len < 1) 2026 return WLAN_STATUS_UNSPECIFIED_FAILURE; 2027 epos++; /* skip ext ID */ 2028 len--; 2029 2030 if (sae->tmp->pw_id && 2031 (len != os_strlen(sae->tmp->pw_id) || 2032 os_memcmp(sae->tmp->pw_id, epos, len) != 0)) { 2033 wpa_printf(MSG_DEBUG, 2034 "SAE: The included Password Identifier does not match the expected one (%s)", 2035 sae->tmp->pw_id); 2036 return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER; 2037 } 2038 2039 os_free(sae->tmp->pw_id); 2040 sae->tmp->pw_id = os_malloc(len + 1); 2041 if (!sae->tmp->pw_id) 2042 return WLAN_STATUS_UNSPECIFIED_FAILURE; 2043 os_memcpy(sae->tmp->pw_id, epos, len); 2044 sae->tmp->pw_id[len] = '\0'; 2045 wpa_hexdump_ascii(MSG_DEBUG, "SAE: Received Password Identifier", 2046 sae->tmp->pw_id, len); 2047 *pos = epos + len; 2048 return WLAN_STATUS_SUCCESS; 2049 } 2050 2051 2052 static int sae_parse_rejected_groups(struct sae_data *sae, 2053 const u8 **pos, const u8 *end) 2054 { 2055 const u8 *epos; 2056 u8 len; 2057 2058 wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame", 2059 *pos, end - *pos); 2060 if (!sae_is_rejected_groups_elem(*pos, end)) 2061 return WLAN_STATUS_SUCCESS; 2062 2063 epos = *pos; 2064 epos++; /* skip IE type */ 2065 len = *epos++; /* IE length */ 2066 if (len > end - epos || len < 1) 2067 return WLAN_STATUS_UNSPECIFIED_FAILURE; 2068 epos++; /* skip ext ID */ 2069 len--; 2070 2071 wpabuf_free(sae->tmp->peer_rejected_groups); 2072 sae->tmp->peer_rejected_groups = wpabuf_alloc(len); 2073 if (!sae->tmp->peer_rejected_groups) 2074 return WLAN_STATUS_UNSPECIFIED_FAILURE; 2075 wpabuf_put_data(sae->tmp->peer_rejected_groups, epos, len); 2076 wpa_hexdump_buf(MSG_DEBUG, "SAE: Received Rejected Groups list", 2077 sae->tmp->peer_rejected_groups); 2078 *pos = epos + len; 2079 return WLAN_STATUS_SUCCESS; 2080 } 2081 2082 2083 u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len, 2084 const u8 **token, size_t *token_len, int *allowed_groups, 2085 int h2e) 2086 { 2087 const u8 *pos = data, *end = data + len; 2088 u16 res; 2089 2090 /* Check Finite Cyclic Group */ 2091 if (end - pos < 2) 2092 return WLAN_STATUS_UNSPECIFIED_FAILURE; 2093 res = sae_group_allowed(sae, allowed_groups, WPA_GET_LE16(pos)); 2094 if (res != WLAN_STATUS_SUCCESS) 2095 return res; 2096 pos += 2; 2097 2098 /* Optional Anti-Clogging Token */ 2099 sae_parse_commit_token(sae, &pos, end, token, token_len, h2e); 2100 2101 /* commit-scalar */ 2102 res = sae_parse_commit_scalar(sae, &pos, end); 2103 if (res != WLAN_STATUS_SUCCESS) 2104 return res; 2105 2106 /* commit-element */ 2107 res = sae_parse_commit_element(sae, &pos, end); 2108 if (res != WLAN_STATUS_SUCCESS) 2109 return res; 2110 2111 /* Optional Password Identifier element */ 2112 res = sae_parse_password_identifier(sae, &pos, end); 2113 if (res != WLAN_STATUS_SUCCESS) 2114 return res; 2115 2116 /* Conditional Rejected Groups element */ 2117 if (h2e) { 2118 res = sae_parse_rejected_groups(sae, &pos, end); 2119 if (res != WLAN_STATUS_SUCCESS) 2120 return res; 2121 } 2122 2123 /* Optional Anti-Clogging Token Container element */ 2124 if (h2e) 2125 sae_parse_token_container(sae, pos, end, token, token_len); 2126 2127 /* 2128 * Check whether peer-commit-scalar and PEER-COMMIT-ELEMENT are same as 2129 * the values we sent which would be evidence of a reflection attack. 2130 */ 2131 if (!sae->tmp->own_commit_scalar || 2132 crypto_bignum_cmp(sae->tmp->own_commit_scalar, 2133 sae->peer_commit_scalar) != 0 || 2134 (sae->tmp->dh && 2135 (!sae->tmp->own_commit_element_ffc || 2136 crypto_bignum_cmp(sae->tmp->own_commit_element_ffc, 2137 sae->tmp->peer_commit_element_ffc) != 0)) || 2138 (sae->tmp->ec && 2139 (!sae->tmp->own_commit_element_ecc || 2140 crypto_ec_point_cmp(sae->tmp->ec, 2141 sae->tmp->own_commit_element_ecc, 2142 sae->tmp->peer_commit_element_ecc) != 0))) 2143 return WLAN_STATUS_SUCCESS; /* scalars/elements are different */ 2144 2145 /* 2146 * This is a reflection attack - return special value to trigger caller 2147 * to silently discard the frame instead of replying with a specific 2148 * status code. 2149 */ 2150 return SAE_SILENTLY_DISCARD; 2151 } 2152 2153 2154 static int sae_cn_confirm(struct sae_data *sae, const u8 *sc, 2155 const struct crypto_bignum *scalar1, 2156 const u8 *element1, size_t element1_len, 2157 const struct crypto_bignum *scalar2, 2158 const u8 *element2, size_t element2_len, 2159 u8 *confirm) 2160 { 2161 const u8 *addr[5]; 2162 size_t len[5]; 2163 u8 scalar_b1[SAE_MAX_PRIME_LEN], scalar_b2[SAE_MAX_PRIME_LEN]; 2164 2165 /* Confirm 2166 * CN(key, X, Y, Z, ...) = 2167 * HMAC-SHA256(key, D2OS(X) || D2OS(Y) || D2OS(Z) | ...) 2168 * confirm = CN(KCK, send-confirm, commit-scalar, COMMIT-ELEMENT, 2169 * peer-commit-scalar, PEER-COMMIT-ELEMENT) 2170 * verifier = CN(KCK, peer-send-confirm, peer-commit-scalar, 2171 * PEER-COMMIT-ELEMENT, commit-scalar, COMMIT-ELEMENT) 2172 */ 2173 if (crypto_bignum_to_bin(scalar1, scalar_b1, sizeof(scalar_b1), 2174 sae->tmp->prime_len) < 0 || 2175 crypto_bignum_to_bin(scalar2, scalar_b2, sizeof(scalar_b2), 2176 sae->tmp->prime_len) < 0) 2177 return -1; 2178 addr[0] = sc; 2179 len[0] = 2; 2180 addr[1] = scalar_b1; 2181 len[1] = sae->tmp->prime_len; 2182 addr[2] = element1; 2183 len[2] = element1_len; 2184 addr[3] = scalar_b2; 2185 len[3] = sae->tmp->prime_len; 2186 addr[4] = element2; 2187 len[4] = element2_len; 2188 return hkdf_extract(sae->tmp->kck_len, sae->tmp->kck, sae->tmp->kck_len, 2189 5, addr, len, confirm); 2190 } 2191 2192 2193 static int sae_cn_confirm_ecc(struct sae_data *sae, const u8 *sc, 2194 const struct crypto_bignum *scalar1, 2195 const struct crypto_ec_point *element1, 2196 const struct crypto_bignum *scalar2, 2197 const struct crypto_ec_point *element2, 2198 u8 *confirm) 2199 { 2200 u8 element_b1[2 * SAE_MAX_ECC_PRIME_LEN]; 2201 u8 element_b2[2 * SAE_MAX_ECC_PRIME_LEN]; 2202 2203 if (crypto_ec_point_to_bin(sae->tmp->ec, element1, element_b1, 2204 element_b1 + sae->tmp->prime_len) < 0 || 2205 crypto_ec_point_to_bin(sae->tmp->ec, element2, element_b2, 2206 element_b2 + sae->tmp->prime_len) < 0 || 2207 sae_cn_confirm(sae, sc, scalar1, element_b1, 2208 2 * sae->tmp->prime_len, 2209 scalar2, element_b2, 2 * sae->tmp->prime_len, 2210 confirm) < 0) 2211 return -1; 2212 return 0; 2213 } 2214 2215 2216 static int sae_cn_confirm_ffc(struct sae_data *sae, const u8 *sc, 2217 const struct crypto_bignum *scalar1, 2218 const struct crypto_bignum *element1, 2219 const struct crypto_bignum *scalar2, 2220 const struct crypto_bignum *element2, 2221 u8 *confirm) 2222 { 2223 u8 element_b1[SAE_MAX_PRIME_LEN]; 2224 u8 element_b2[SAE_MAX_PRIME_LEN]; 2225 2226 if (crypto_bignum_to_bin(element1, element_b1, sizeof(element_b1), 2227 sae->tmp->prime_len) < 0 || 2228 crypto_bignum_to_bin(element2, element_b2, sizeof(element_b2), 2229 sae->tmp->prime_len) < 0 || 2230 sae_cn_confirm(sae, sc, scalar1, element_b1, sae->tmp->prime_len, 2231 scalar2, element_b2, sae->tmp->prime_len, 2232 confirm) < 0) 2233 return -1; 2234 return 0; 2235 } 2236 2237 2238 int sae_write_confirm(struct sae_data *sae, struct wpabuf *buf) 2239 { 2240 const u8 *sc; 2241 size_t hash_len; 2242 int res; 2243 2244 if (sae->tmp == NULL) 2245 return -1; 2246 2247 hash_len = sae->tmp->kck_len; 2248 2249 /* Send-Confirm */ 2250 if (sae->send_confirm < 0xffff) 2251 sae->send_confirm++; 2252 sc = wpabuf_put(buf, 0); 2253 wpabuf_put_le16(buf, sae->send_confirm); 2254 2255 if (sae->tmp->ec) 2256 res = sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar, 2257 sae->tmp->own_commit_element_ecc, 2258 sae->peer_commit_scalar, 2259 sae->tmp->peer_commit_element_ecc, 2260 wpabuf_put(buf, hash_len)); 2261 else 2262 res = sae_cn_confirm_ffc(sae, sc, sae->tmp->own_commit_scalar, 2263 sae->tmp->own_commit_element_ffc, 2264 sae->peer_commit_scalar, 2265 sae->tmp->peer_commit_element_ffc, 2266 wpabuf_put(buf, hash_len)); 2267 if (res) 2268 return res; 2269 2270 #ifdef CONFIG_SAE_PK 2271 if (sae_write_confirm_pk(sae, buf) < 0) 2272 return -1; 2273 #endif /* CONFIG_SAE_PK */ 2274 2275 return 0; 2276 } 2277 2278 2279 int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len) 2280 { 2281 u8 verifier[SAE_MAX_HASH_LEN]; 2282 size_t hash_len; 2283 2284 if (!sae->tmp) 2285 return -1; 2286 2287 hash_len = sae->tmp->kck_len; 2288 if (len < 2 + hash_len) { 2289 wpa_printf(MSG_DEBUG, "SAE: Too short confirm message"); 2290 return -1; 2291 } 2292 2293 wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", WPA_GET_LE16(data)); 2294 2295 if (!sae->peer_commit_scalar || !sae->tmp->own_commit_scalar) { 2296 wpa_printf(MSG_DEBUG, "SAE: Temporary data not yet available"); 2297 return -1; 2298 } 2299 2300 if (sae->tmp->ec) { 2301 if (!sae->tmp->peer_commit_element_ecc || 2302 !sae->tmp->own_commit_element_ecc || 2303 sae_cn_confirm_ecc(sae, data, sae->peer_commit_scalar, 2304 sae->tmp->peer_commit_element_ecc, 2305 sae->tmp->own_commit_scalar, 2306 sae->tmp->own_commit_element_ecc, 2307 verifier) < 0) 2308 return -1; 2309 } else { 2310 if (!sae->tmp->peer_commit_element_ffc || 2311 !sae->tmp->own_commit_element_ffc || 2312 sae_cn_confirm_ffc(sae, data, sae->peer_commit_scalar, 2313 sae->tmp->peer_commit_element_ffc, 2314 sae->tmp->own_commit_scalar, 2315 sae->tmp->own_commit_element_ffc, 2316 verifier) < 0) 2317 return -1; 2318 } 2319 2320 if (os_memcmp_const(verifier, data + 2, hash_len) != 0) { 2321 wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch"); 2322 wpa_hexdump(MSG_DEBUG, "SAE: Received confirm", 2323 data + 2, hash_len); 2324 wpa_hexdump(MSG_DEBUG, "SAE: Calculated verifier", 2325 verifier, hash_len); 2326 return -1; 2327 } 2328 2329 #ifdef CONFIG_SAE_PK 2330 if (sae_check_confirm_pk(sae, data + 2 + hash_len, 2331 len - 2 - hash_len) < 0) 2332 return -1; 2333 #endif /* CONFIG_SAE_PK */ 2334 2335 return 0; 2336 } 2337 2338 2339 const char * sae_state_txt(enum sae_state state) 2340 { 2341 switch (state) { 2342 case SAE_NOTHING: 2343 return "Nothing"; 2344 case SAE_COMMITTED: 2345 return "Committed"; 2346 case SAE_CONFIRMED: 2347 return "Confirmed"; 2348 case SAE_ACCEPTED: 2349 return "Accepted"; 2350 } 2351 return "?"; 2352 } 2353