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/random.h" 16 #include "crypto/dh_groups.h" 17 #include "ieee802_11_defs.h" 18 #include "sae.h" 19 20 21 int sae_set_group(struct sae_data *sae, int group) 22 { 23 struct sae_temporary_data *tmp; 24 25 sae_clear_data(sae); 26 tmp = sae->tmp = os_zalloc(sizeof(*tmp)); 27 if (tmp == NULL) 28 return -1; 29 30 /* First, check if this is an ECC group */ 31 tmp->ec = crypto_ec_init(group); 32 if (tmp->ec) { 33 wpa_printf(MSG_DEBUG, "SAE: Selecting supported ECC group %d", 34 group); 35 sae->group = group; 36 tmp->prime_len = crypto_ec_prime_len(tmp->ec); 37 tmp->prime = crypto_ec_get_prime(tmp->ec); 38 tmp->order = crypto_ec_get_order(tmp->ec); 39 return 0; 40 } 41 42 /* Not an ECC group, check FFC */ 43 tmp->dh = dh_groups_get(group); 44 if (tmp->dh) { 45 wpa_printf(MSG_DEBUG, "SAE: Selecting supported FFC group %d", 46 group); 47 sae->group = group; 48 tmp->prime_len = tmp->dh->prime_len; 49 if (tmp->prime_len > SAE_MAX_PRIME_LEN) { 50 sae_clear_data(sae); 51 return -1; 52 } 53 54 tmp->prime_buf = crypto_bignum_init_set(tmp->dh->prime, 55 tmp->prime_len); 56 if (tmp->prime_buf == NULL) { 57 sae_clear_data(sae); 58 return -1; 59 } 60 tmp->prime = tmp->prime_buf; 61 62 tmp->order_buf = crypto_bignum_init_set(tmp->dh->order, 63 tmp->dh->order_len); 64 if (tmp->order_buf == NULL) { 65 sae_clear_data(sae); 66 return -1; 67 } 68 tmp->order = tmp->order_buf; 69 70 return 0; 71 } 72 73 /* Unsupported group */ 74 wpa_printf(MSG_DEBUG, 75 "SAE: Group %d not supported by the crypto library", group); 76 return -1; 77 } 78 79 80 void sae_clear_temp_data(struct sae_data *sae) 81 { 82 struct sae_temporary_data *tmp; 83 if (sae == NULL || sae->tmp == NULL) 84 return; 85 tmp = sae->tmp; 86 crypto_ec_deinit(tmp->ec); 87 crypto_bignum_deinit(tmp->prime_buf, 0); 88 crypto_bignum_deinit(tmp->order_buf, 0); 89 crypto_bignum_deinit(tmp->sae_rand, 1); 90 crypto_bignum_deinit(tmp->pwe_ffc, 1); 91 crypto_bignum_deinit(tmp->own_commit_scalar, 0); 92 crypto_bignum_deinit(tmp->own_commit_element_ffc, 0); 93 crypto_bignum_deinit(tmp->peer_commit_element_ffc, 0); 94 crypto_ec_point_deinit(tmp->pwe_ecc, 1); 95 crypto_ec_point_deinit(tmp->own_commit_element_ecc, 0); 96 crypto_ec_point_deinit(tmp->peer_commit_element_ecc, 0); 97 wpabuf_free(tmp->anti_clogging_token); 98 os_free(tmp->pw_id); 99 bin_clear_free(tmp, sizeof(*tmp)); 100 sae->tmp = NULL; 101 } 102 103 104 void sae_clear_data(struct sae_data *sae) 105 { 106 if (sae == NULL) 107 return; 108 sae_clear_temp_data(sae); 109 crypto_bignum_deinit(sae->peer_commit_scalar, 0); 110 os_memset(sae, 0, sizeof(*sae)); 111 } 112 113 114 static void buf_shift_right(u8 *buf, size_t len, size_t bits) 115 { 116 size_t i; 117 for (i = len - 1; i > 0; i--) 118 buf[i] = (buf[i - 1] << (8 - bits)) | (buf[i] >> bits); 119 buf[0] >>= bits; 120 } 121 122 123 static struct crypto_bignum * sae_get_rand(struct sae_data *sae) 124 { 125 u8 val[SAE_MAX_PRIME_LEN]; 126 int iter = 0; 127 struct crypto_bignum *bn = NULL; 128 int order_len_bits = crypto_bignum_bits(sae->tmp->order); 129 size_t order_len = (order_len_bits + 7) / 8; 130 131 if (order_len > sizeof(val)) 132 return NULL; 133 134 for (;;) { 135 if (iter++ > 100 || random_get_bytes(val, order_len) < 0) 136 return NULL; 137 if (order_len_bits % 8) 138 buf_shift_right(val, order_len, 8 - order_len_bits % 8); 139 bn = crypto_bignum_init_set(val, order_len); 140 if (bn == NULL) 141 return NULL; 142 if (crypto_bignum_is_zero(bn) || 143 crypto_bignum_is_one(bn) || 144 crypto_bignum_cmp(bn, sae->tmp->order) >= 0) { 145 crypto_bignum_deinit(bn, 0); 146 continue; 147 } 148 break; 149 } 150 151 os_memset(val, 0, order_len); 152 return bn; 153 } 154 155 156 static struct crypto_bignum * sae_get_rand_and_mask(struct sae_data *sae) 157 { 158 crypto_bignum_deinit(sae->tmp->sae_rand, 1); 159 sae->tmp->sae_rand = sae_get_rand(sae); 160 if (sae->tmp->sae_rand == NULL) 161 return NULL; 162 return sae_get_rand(sae); 163 } 164 165 166 static void sae_pwd_seed_key(const u8 *addr1, const u8 *addr2, u8 *key) 167 { 168 wpa_printf(MSG_DEBUG, "SAE: PWE derivation - addr1=" MACSTR 169 " addr2=" MACSTR, MAC2STR(addr1), MAC2STR(addr2)); 170 if (os_memcmp(addr1, addr2, ETH_ALEN) > 0) { 171 os_memcpy(key, addr1, ETH_ALEN); 172 os_memcpy(key + ETH_ALEN, addr2, ETH_ALEN); 173 } else { 174 os_memcpy(key, addr2, ETH_ALEN); 175 os_memcpy(key + ETH_ALEN, addr1, ETH_ALEN); 176 } 177 } 178 179 180 static struct crypto_bignum * 181 get_rand_1_to_p_1(const u8 *prime, size_t prime_len, size_t prime_bits, 182 int *r_odd) 183 { 184 for (;;) { 185 struct crypto_bignum *r; 186 u8 tmp[SAE_MAX_ECC_PRIME_LEN]; 187 188 if (random_get_bytes(tmp, prime_len) < 0) 189 break; 190 if (prime_bits % 8) 191 buf_shift_right(tmp, prime_len, 8 - prime_bits % 8); 192 if (os_memcmp(tmp, prime, prime_len) >= 0) 193 continue; 194 r = crypto_bignum_init_set(tmp, prime_len); 195 if (!r) 196 break; 197 if (crypto_bignum_is_zero(r)) { 198 crypto_bignum_deinit(r, 0); 199 continue; 200 } 201 202 *r_odd = tmp[prime_len - 1] & 0x01; 203 return r; 204 } 205 206 return NULL; 207 } 208 209 210 static int is_quadratic_residue_blind(struct sae_data *sae, 211 const u8 *prime, size_t bits, 212 const u8 *qr, const u8 *qnr, 213 const struct crypto_bignum *y_sqr) 214 { 215 struct crypto_bignum *r, *num, *qr_or_qnr = NULL; 216 int r_odd, check, res = -1; 217 u8 qr_or_qnr_bin[SAE_MAX_ECC_PRIME_LEN]; 218 size_t prime_len = sae->tmp->prime_len; 219 unsigned int mask; 220 221 /* 222 * Use the blinding technique to mask y_sqr while determining 223 * whether it is a quadratic residue modulo p to avoid leaking 224 * timing information while determining the Legendre symbol. 225 * 226 * v = y_sqr 227 * r = a random number between 1 and p-1, inclusive 228 * num = (v * r * r) modulo p 229 */ 230 r = get_rand_1_to_p_1(prime, prime_len, bits, &r_odd); 231 if (!r) 232 return -1; 233 234 num = crypto_bignum_init(); 235 if (!num || 236 crypto_bignum_mulmod(y_sqr, r, sae->tmp->prime, num) < 0 || 237 crypto_bignum_mulmod(num, r, sae->tmp->prime, num) < 0) 238 goto fail; 239 240 /* 241 * Need to minimize differences in handling different cases, so try to 242 * avoid branches and timing differences. 243 * 244 * If r_odd: 245 * num = (num * qr) module p 246 * LGR(num, p) = 1 ==> quadratic residue 247 * else: 248 * num = (num * qnr) module p 249 * LGR(num, p) = -1 ==> quadratic residue 250 */ 251 mask = const_time_is_zero(r_odd); 252 const_time_select_bin(mask, qnr, qr, prime_len, qr_or_qnr_bin); 253 qr_or_qnr = crypto_bignum_init_set(qr_or_qnr_bin, prime_len); 254 if (!qr_or_qnr || 255 crypto_bignum_mulmod(num, qr_or_qnr, sae->tmp->prime, num) < 0) 256 goto fail; 257 /* r_odd is 0 or 1; branchless version of check = r_odd ? 1 : -1, */ 258 check = const_time_select_int(mask, -1, 1); 259 260 res = crypto_bignum_legendre(num, sae->tmp->prime); 261 if (res == -2) { 262 res = -1; 263 goto fail; 264 } 265 /* branchless version of res = res == check 266 * (res is -1, 0, or 1; check is -1 or 1) */ 267 mask = const_time_eq(res, check); 268 res = const_time_select_int(mask, 1, 0); 269 fail: 270 crypto_bignum_deinit(num, 1); 271 crypto_bignum_deinit(r, 1); 272 crypto_bignum_deinit(qr_or_qnr, 1); 273 return res; 274 } 275 276 277 static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed, 278 const u8 *prime, const u8 *qr, const u8 *qnr, 279 u8 *pwd_value) 280 { 281 struct crypto_bignum *y_sqr, *x_cand; 282 int res; 283 size_t bits; 284 int cmp_prime; 285 unsigned int in_range; 286 287 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN); 288 289 /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */ 290 bits = crypto_ec_prime_len_bits(sae->tmp->ec); 291 if (sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking", 292 prime, sae->tmp->prime_len, pwd_value, bits) < 0) 293 return -1; 294 if (bits % 8) 295 buf_shift_right(pwd_value, sae->tmp->prime_len, 8 - bits % 8); 296 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", 297 pwd_value, sae->tmp->prime_len); 298 299 cmp_prime = const_time_memcmp(pwd_value, prime, sae->tmp->prime_len); 300 /* Create a const_time mask for selection based on prf result 301 * being smaller than prime. */ 302 in_range = const_time_fill_msb((unsigned int) cmp_prime); 303 /* The algorithm description would skip the next steps if 304 * cmp_prime >= 0 (reutnr 0 here), but go through them regardless to 305 * minimize externally observable differences in behavior. */ 306 307 x_cand = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len); 308 if (!x_cand) 309 return -1; 310 y_sqr = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x_cand); 311 crypto_bignum_deinit(x_cand, 1); 312 if (!y_sqr) 313 return -1; 314 315 res = is_quadratic_residue_blind(sae, prime, bits, qr, qnr, y_sqr); 316 crypto_bignum_deinit(y_sqr, 1); 317 if (res < 0) 318 return res; 319 return const_time_select_int(in_range, res, 0); 320 } 321 322 323 /* Returns -1 on fatal failure, 0 if PWE cannot be derived from the provided 324 * pwd-seed, or 1 if a valid PWE was derived from pwd-seed. */ 325 static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed, 326 struct crypto_bignum *pwe) 327 { 328 u8 pwd_value[SAE_MAX_PRIME_LEN]; 329 size_t bits = sae->tmp->prime_len * 8; 330 u8 exp[1]; 331 struct crypto_bignum *a, *b = NULL; 332 int res, is_val; 333 u8 pwd_value_valid; 334 335 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN); 336 337 /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */ 338 if (sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking", 339 sae->tmp->dh->prime, sae->tmp->prime_len, pwd_value, 340 bits) < 0) 341 return -1; 342 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", pwd_value, 343 sae->tmp->prime_len); 344 345 /* Check whether pwd-value < p */ 346 res = const_time_memcmp(pwd_value, sae->tmp->dh->prime, 347 sae->tmp->prime_len); 348 /* pwd-value >= p is invalid, so res is < 0 for the valid cases and 349 * the negative sign can be used to fill the mask for constant time 350 * selection */ 351 pwd_value_valid = const_time_fill_msb(res); 352 353 /* If pwd-value >= p, force pwd-value to be < p and perform the 354 * calculations anyway to hide timing difference. The derived PWE will 355 * be ignored in that case. */ 356 pwd_value[0] = const_time_select_u8(pwd_value_valid, pwd_value[0], 0); 357 358 /* PWE = pwd-value^((p-1)/r) modulo p */ 359 360 res = -1; 361 a = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len); 362 if (!a) 363 goto fail; 364 365 /* This is an optimization based on the used group that does not depend 366 * on the password in any way, so it is fine to use separate branches 367 * for this step without constant time operations. */ 368 if (sae->tmp->dh->safe_prime) { 369 /* 370 * r = (p-1)/2 for the group used here, so this becomes: 371 * PWE = pwd-value^2 modulo p 372 */ 373 exp[0] = 2; 374 b = crypto_bignum_init_set(exp, sizeof(exp)); 375 } else { 376 /* Calculate exponent: (p-1)/r */ 377 exp[0] = 1; 378 b = crypto_bignum_init_set(exp, sizeof(exp)); 379 if (b == NULL || 380 crypto_bignum_sub(sae->tmp->prime, b, b) < 0 || 381 crypto_bignum_div(b, sae->tmp->order, b) < 0) 382 goto fail; 383 } 384 385 if (!b) 386 goto fail; 387 388 res = crypto_bignum_exptmod(a, b, sae->tmp->prime, pwe); 389 if (res < 0) 390 goto fail; 391 392 /* There were no fatal errors in calculations, so determine the return 393 * value using constant time operations. We get here for number of 394 * invalid cases which are cleared here after having performed all the 395 * computation. PWE is valid if pwd-value was less than prime and 396 * PWE > 1. Start with pwd-value check first and then use constant time 397 * operations to clear res to 0 if PWE is 0 or 1. 398 */ 399 res = const_time_select_u8(pwd_value_valid, 1, 0); 400 is_val = crypto_bignum_is_zero(pwe); 401 res = const_time_select_u8(const_time_is_zero(is_val), res, 0); 402 is_val = crypto_bignum_is_one(pwe); 403 res = const_time_select_u8(const_time_is_zero(is_val), res, 0); 404 405 fail: 406 crypto_bignum_deinit(a, 1); 407 crypto_bignum_deinit(b, 1); 408 return res; 409 } 410 411 412 static int get_random_qr_qnr(const u8 *prime, size_t prime_len, 413 const struct crypto_bignum *prime_bn, 414 size_t prime_bits, struct crypto_bignum **qr, 415 struct crypto_bignum **qnr) 416 { 417 *qr = NULL; 418 *qnr = NULL; 419 420 while (!(*qr) || !(*qnr)) { 421 u8 tmp[SAE_MAX_ECC_PRIME_LEN]; 422 struct crypto_bignum *q; 423 int res; 424 425 if (random_get_bytes(tmp, prime_len) < 0) 426 break; 427 if (prime_bits % 8) 428 buf_shift_right(tmp, prime_len, 8 - prime_bits % 8); 429 if (os_memcmp(tmp, prime, prime_len) >= 0) 430 continue; 431 q = crypto_bignum_init_set(tmp, prime_len); 432 if (!q) 433 break; 434 res = crypto_bignum_legendre(q, prime_bn); 435 436 if (res == 1 && !(*qr)) 437 *qr = q; 438 else if (res == -1 && !(*qnr)) 439 *qnr = q; 440 else 441 crypto_bignum_deinit(q, 0); 442 } 443 444 return (*qr && *qnr) ? 0 : -1; 445 } 446 447 448 static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1, 449 const u8 *addr2, const u8 *password, 450 size_t password_len, const char *identifier) 451 { 452 u8 counter, k = 40; 453 u8 addrs[2 * ETH_ALEN]; 454 const u8 *addr[3]; 455 size_t len[3]; 456 size_t num_elem; 457 u8 *dummy_password, *tmp_password; 458 int pwd_seed_odd = 0; 459 u8 prime[SAE_MAX_ECC_PRIME_LEN]; 460 size_t prime_len; 461 struct crypto_bignum *x = NULL, *qr = NULL, *qnr = NULL; 462 u8 x_bin[SAE_MAX_ECC_PRIME_LEN]; 463 u8 x_cand_bin[SAE_MAX_ECC_PRIME_LEN]; 464 u8 qr_bin[SAE_MAX_ECC_PRIME_LEN]; 465 u8 qnr_bin[SAE_MAX_ECC_PRIME_LEN]; 466 size_t bits; 467 int res = -1; 468 u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_* 469 * mask */ 470 471 os_memset(x_bin, 0, sizeof(x_bin)); 472 473 dummy_password = os_malloc(password_len); 474 tmp_password = os_malloc(password_len); 475 if (!dummy_password || !tmp_password || 476 random_get_bytes(dummy_password, password_len) < 0) 477 goto fail; 478 479 prime_len = sae->tmp->prime_len; 480 if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime), 481 prime_len) < 0) 482 goto fail; 483 bits = crypto_ec_prime_len_bits(sae->tmp->ec); 484 485 /* 486 * Create a random quadratic residue (qr) and quadratic non-residue 487 * (qnr) modulo p for blinding purposes during the loop. 488 */ 489 if (get_random_qr_qnr(prime, prime_len, sae->tmp->prime, bits, 490 &qr, &qnr) < 0 || 491 crypto_bignum_to_bin(qr, qr_bin, sizeof(qr_bin), prime_len) < 0 || 492 crypto_bignum_to_bin(qnr, qnr_bin, sizeof(qnr_bin), prime_len) < 0) 493 goto fail; 494 495 wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password", 496 password, password_len); 497 if (identifier) 498 wpa_printf(MSG_DEBUG, "SAE: password identifier: %s", 499 identifier); 500 501 /* 502 * H(salt, ikm) = HMAC-SHA256(salt, ikm) 503 * base = password [|| identifier] 504 * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC), 505 * base || counter) 506 */ 507 sae_pwd_seed_key(addr1, addr2, addrs); 508 509 addr[0] = tmp_password; 510 len[0] = password_len; 511 num_elem = 1; 512 if (identifier) { 513 addr[num_elem] = (const u8 *) identifier; 514 len[num_elem] = os_strlen(identifier); 515 num_elem++; 516 } 517 addr[num_elem] = &counter; 518 len[num_elem] = sizeof(counter); 519 num_elem++; 520 521 /* 522 * Continue for at least k iterations to protect against side-channel 523 * attacks that attempt to determine the number of iterations required 524 * in the loop. 525 */ 526 for (counter = 1; counter <= k || !found; counter++) { 527 u8 pwd_seed[SHA256_MAC_LEN]; 528 529 if (counter > 200) { 530 /* This should not happen in practice */ 531 wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE"); 532 break; 533 } 534 535 wpa_printf(MSG_DEBUG, "SAE: counter = %03u", counter); 536 const_time_select_bin(found, dummy_password, password, 537 password_len, tmp_password); 538 if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem, 539 addr, len, pwd_seed) < 0) 540 break; 541 542 res = sae_test_pwd_seed_ecc(sae, pwd_seed, 543 prime, qr_bin, qnr_bin, x_cand_bin); 544 const_time_select_bin(found, x_bin, x_cand_bin, prime_len, 545 x_bin); 546 pwd_seed_odd = const_time_select_u8( 547 found, pwd_seed_odd, 548 pwd_seed[SHA256_MAC_LEN - 1] & 0x01); 549 os_memset(pwd_seed, 0, sizeof(pwd_seed)); 550 if (res < 0) 551 goto fail; 552 /* Need to minimize differences in handling res == 0 and 1 here 553 * to avoid differences in timing and instruction cache access, 554 * so use const_time_select_*() to make local copies of the 555 * values based on whether this loop iteration was the one that 556 * found the pwd-seed/x. */ 557 558 /* found is 0 or 0xff here and res is 0 or 1. Bitwise OR of them 559 * (with res converted to 0/0xff) handles this in constant time. 560 */ 561 found |= res * 0xff; 562 wpa_printf(MSG_DEBUG, "SAE: pwd-seed result %d found=0x%02x", 563 res, found); 564 } 565 566 if (!found) { 567 wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE"); 568 res = -1; 569 goto fail; 570 } 571 572 x = crypto_bignum_init_set(x_bin, prime_len); 573 if (!x) { 574 res = -1; 575 goto fail; 576 } 577 578 if (!sae->tmp->pwe_ecc) 579 sae->tmp->pwe_ecc = crypto_ec_point_init(sae->tmp->ec); 580 if (!sae->tmp->pwe_ecc) 581 res = -1; 582 else 583 res = crypto_ec_point_solve_y_coord(sae->tmp->ec, 584 sae->tmp->pwe_ecc, x, 585 pwd_seed_odd); 586 if (res < 0) { 587 /* 588 * This should not happen since we already checked that there 589 * is a result. 590 */ 591 wpa_printf(MSG_DEBUG, "SAE: Could not solve y"); 592 } 593 594 fail: 595 crypto_bignum_deinit(qr, 0); 596 crypto_bignum_deinit(qnr, 0); 597 os_free(dummy_password); 598 bin_clear_free(tmp_password, password_len); 599 crypto_bignum_deinit(x, 1); 600 os_memset(x_bin, 0, sizeof(x_bin)); 601 os_memset(x_cand_bin, 0, sizeof(x_cand_bin)); 602 603 return res; 604 } 605 606 607 static int sae_modp_group_require_masking(int group) 608 { 609 /* Groups for which pwd-value is likely to be >= p frequently */ 610 return group == 22 || group == 23 || group == 24; 611 } 612 613 614 static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1, 615 const u8 *addr2, const u8 *password, 616 size_t password_len, const char *identifier) 617 { 618 u8 counter, k, sel_counter = 0; 619 u8 addrs[2 * ETH_ALEN]; 620 const u8 *addr[3]; 621 size_t len[3]; 622 size_t num_elem; 623 u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_* 624 * mask */ 625 u8 mask; 626 struct crypto_bignum *pwe; 627 size_t prime_len = sae->tmp->prime_len * 8; 628 u8 *pwe_buf; 629 630 crypto_bignum_deinit(sae->tmp->pwe_ffc, 1); 631 sae->tmp->pwe_ffc = NULL; 632 633 /* Allocate a buffer to maintain selected and candidate PWE for constant 634 * time selection. */ 635 pwe_buf = os_zalloc(prime_len * 2); 636 pwe = crypto_bignum_init(); 637 if (!pwe_buf || !pwe) 638 goto fail; 639 640 wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password", 641 password, password_len); 642 643 /* 644 * H(salt, ikm) = HMAC-SHA256(salt, ikm) 645 * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC), 646 * password [|| identifier] || counter) 647 */ 648 sae_pwd_seed_key(addr1, addr2, addrs); 649 650 addr[0] = password; 651 len[0] = password_len; 652 num_elem = 1; 653 if (identifier) { 654 addr[num_elem] = (const u8 *) identifier; 655 len[num_elem] = os_strlen(identifier); 656 num_elem++; 657 } 658 addr[num_elem] = &counter; 659 len[num_elem] = sizeof(counter); 660 num_elem++; 661 662 k = sae_modp_group_require_masking(sae->group) ? 40 : 1; 663 664 for (counter = 1; counter <= k || !found; counter++) { 665 u8 pwd_seed[SHA256_MAC_LEN]; 666 int res; 667 668 if (counter > 200) { 669 /* This should not happen in practice */ 670 wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE"); 671 break; 672 } 673 674 wpa_printf(MSG_DEBUG, "SAE: counter = %02u", counter); 675 if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem, 676 addr, len, pwd_seed) < 0) 677 break; 678 res = sae_test_pwd_seed_ffc(sae, pwd_seed, pwe); 679 /* res is -1 for fatal failure, 0 if a valid PWE was not found, 680 * or 1 if a valid PWE was found. */ 681 if (res < 0) 682 break; 683 /* Store the candidate PWE into the second half of pwe_buf and 684 * the selected PWE in the beginning of pwe_buf using constant 685 * time selection. */ 686 if (crypto_bignum_to_bin(pwe, pwe_buf + prime_len, prime_len, 687 prime_len) < 0) 688 break; 689 const_time_select_bin(found, pwe_buf, pwe_buf + prime_len, 690 prime_len, pwe_buf); 691 sel_counter = const_time_select_u8(found, sel_counter, counter); 692 mask = const_time_eq_u8(res, 1); 693 found = const_time_select_u8(found, found, mask); 694 } 695 696 if (!found) 697 goto fail; 698 699 wpa_printf(MSG_DEBUG, "SAE: Use PWE from counter = %02u", sel_counter); 700 sae->tmp->pwe_ffc = crypto_bignum_init_set(pwe_buf, prime_len); 701 fail: 702 crypto_bignum_deinit(pwe, 1); 703 bin_clear_free(pwe_buf, prime_len * 2); 704 return sae->tmp->pwe_ffc ? 0 : -1; 705 } 706 707 708 static int sae_derive_commit_element_ecc(struct sae_data *sae, 709 struct crypto_bignum *mask) 710 { 711 /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */ 712 if (!sae->tmp->own_commit_element_ecc) { 713 sae->tmp->own_commit_element_ecc = 714 crypto_ec_point_init(sae->tmp->ec); 715 if (!sae->tmp->own_commit_element_ecc) 716 return -1; 717 } 718 719 if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc, mask, 720 sae->tmp->own_commit_element_ecc) < 0 || 721 crypto_ec_point_invert(sae->tmp->ec, 722 sae->tmp->own_commit_element_ecc) < 0) { 723 wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element"); 724 return -1; 725 } 726 727 return 0; 728 } 729 730 731 static int sae_derive_commit_element_ffc(struct sae_data *sae, 732 struct crypto_bignum *mask) 733 { 734 /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */ 735 if (!sae->tmp->own_commit_element_ffc) { 736 sae->tmp->own_commit_element_ffc = crypto_bignum_init(); 737 if (!sae->tmp->own_commit_element_ffc) 738 return -1; 739 } 740 741 if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, mask, sae->tmp->prime, 742 sae->tmp->own_commit_element_ffc) < 0 || 743 crypto_bignum_inverse(sae->tmp->own_commit_element_ffc, 744 sae->tmp->prime, 745 sae->tmp->own_commit_element_ffc) < 0) { 746 wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element"); 747 return -1; 748 } 749 750 return 0; 751 } 752 753 754 static int sae_derive_commit(struct sae_data *sae) 755 { 756 struct crypto_bignum *mask; 757 int ret = -1; 758 unsigned int counter = 0; 759 760 do { 761 counter++; 762 if (counter > 100) { 763 /* 764 * This cannot really happen in practice if the random 765 * number generator is working. Anyway, to avoid even a 766 * theoretical infinite loop, break out after 100 767 * attemps. 768 */ 769 return -1; 770 } 771 772 mask = sae_get_rand_and_mask(sae); 773 if (mask == NULL) { 774 wpa_printf(MSG_DEBUG, "SAE: Could not get rand/mask"); 775 return -1; 776 } 777 778 /* commit-scalar = (rand + mask) modulo r */ 779 if (!sae->tmp->own_commit_scalar) { 780 sae->tmp->own_commit_scalar = crypto_bignum_init(); 781 if (!sae->tmp->own_commit_scalar) 782 goto fail; 783 } 784 crypto_bignum_add(sae->tmp->sae_rand, mask, 785 sae->tmp->own_commit_scalar); 786 crypto_bignum_mod(sae->tmp->own_commit_scalar, sae->tmp->order, 787 sae->tmp->own_commit_scalar); 788 } while (crypto_bignum_is_zero(sae->tmp->own_commit_scalar) || 789 crypto_bignum_is_one(sae->tmp->own_commit_scalar)); 790 791 if ((sae->tmp->ec && sae_derive_commit_element_ecc(sae, mask) < 0) || 792 (sae->tmp->dh && sae_derive_commit_element_ffc(sae, mask) < 0)) 793 goto fail; 794 795 ret = 0; 796 fail: 797 crypto_bignum_deinit(mask, 1); 798 return ret; 799 } 800 801 802 int sae_prepare_commit(const u8 *addr1, const u8 *addr2, 803 const u8 *password, size_t password_len, 804 const char *identifier, struct sae_data *sae) 805 { 806 if (sae->tmp == NULL || 807 (sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password, 808 password_len, 809 identifier) < 0) || 810 (sae->tmp->dh && sae_derive_pwe_ffc(sae, addr1, addr2, password, 811 password_len, 812 identifier) < 0) || 813 sae_derive_commit(sae) < 0) 814 return -1; 815 return 0; 816 } 817 818 819 static int sae_derive_k_ecc(struct sae_data *sae, u8 *k) 820 { 821 struct crypto_ec_point *K; 822 int ret = -1; 823 824 K = crypto_ec_point_init(sae->tmp->ec); 825 if (K == NULL) 826 goto fail; 827 828 /* 829 * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE), 830 * PEER-COMMIT-ELEMENT))) 831 * If K is identity element (point-at-infinity), reject 832 * k = F(K) (= x coordinate) 833 */ 834 835 if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc, 836 sae->peer_commit_scalar, K) < 0 || 837 crypto_ec_point_add(sae->tmp->ec, K, 838 sae->tmp->peer_commit_element_ecc, K) < 0 || 839 crypto_ec_point_mul(sae->tmp->ec, K, sae->tmp->sae_rand, K) < 0 || 840 crypto_ec_point_is_at_infinity(sae->tmp->ec, K) || 841 crypto_ec_point_to_bin(sae->tmp->ec, K, k, NULL) < 0) { 842 wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k"); 843 goto fail; 844 } 845 846 wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len); 847 848 ret = 0; 849 fail: 850 crypto_ec_point_deinit(K, 1); 851 return ret; 852 } 853 854 855 static int sae_derive_k_ffc(struct sae_data *sae, u8 *k) 856 { 857 struct crypto_bignum *K; 858 int ret = -1; 859 860 K = crypto_bignum_init(); 861 if (K == NULL) 862 goto fail; 863 864 /* 865 * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE), 866 * PEER-COMMIT-ELEMENT))) 867 * If K is identity element (one), reject. 868 * k = F(K) (= x coordinate) 869 */ 870 871 if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, sae->peer_commit_scalar, 872 sae->tmp->prime, K) < 0 || 873 crypto_bignum_mulmod(K, sae->tmp->peer_commit_element_ffc, 874 sae->tmp->prime, K) < 0 || 875 crypto_bignum_exptmod(K, sae->tmp->sae_rand, sae->tmp->prime, K) < 0 876 || 877 crypto_bignum_is_one(K) || 878 crypto_bignum_to_bin(K, k, SAE_MAX_PRIME_LEN, sae->tmp->prime_len) < 879 0) { 880 wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k"); 881 goto fail; 882 } 883 884 wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len); 885 886 ret = 0; 887 fail: 888 crypto_bignum_deinit(K, 1); 889 return ret; 890 } 891 892 893 static int sae_derive_keys(struct sae_data *sae, const u8 *k) 894 { 895 u8 null_key[SAE_KEYSEED_KEY_LEN], val[SAE_MAX_PRIME_LEN]; 896 u8 keyseed[SHA256_MAC_LEN]; 897 u8 keys[SAE_KCK_LEN + SAE_PMK_LEN]; 898 struct crypto_bignum *tmp; 899 int ret = -1; 900 901 tmp = crypto_bignum_init(); 902 if (tmp == NULL) 903 goto fail; 904 905 /* keyseed = H(<0>32, k) 906 * KCK || PMK = KDF-512(keyseed, "SAE KCK and PMK", 907 * (commit-scalar + peer-commit-scalar) modulo r) 908 * PMKID = L((commit-scalar + peer-commit-scalar) modulo r, 0, 128) 909 */ 910 911 os_memset(null_key, 0, sizeof(null_key)); 912 hmac_sha256(null_key, sizeof(null_key), k, sae->tmp->prime_len, 913 keyseed); 914 wpa_hexdump_key(MSG_DEBUG, "SAE: keyseed", keyseed, sizeof(keyseed)); 915 916 crypto_bignum_add(sae->tmp->own_commit_scalar, sae->peer_commit_scalar, 917 tmp); 918 crypto_bignum_mod(tmp, sae->tmp->order, tmp); 919 crypto_bignum_to_bin(tmp, val, sizeof(val), sae->tmp->prime_len); 920 wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN); 921 if (sha256_prf(keyseed, sizeof(keyseed), "SAE KCK and PMK", 922 val, sae->tmp->prime_len, keys, sizeof(keys)) < 0) 923 goto fail; 924 os_memset(keyseed, 0, sizeof(keyseed)); 925 os_memcpy(sae->tmp->kck, keys, SAE_KCK_LEN); 926 os_memcpy(sae->pmk, keys + SAE_KCK_LEN, SAE_PMK_LEN); 927 os_memcpy(sae->pmkid, val, SAE_PMKID_LEN); 928 os_memset(keys, 0, sizeof(keys)); 929 wpa_hexdump_key(MSG_DEBUG, "SAE: KCK", sae->tmp->kck, SAE_KCK_LEN); 930 wpa_hexdump_key(MSG_DEBUG, "SAE: PMK", sae->pmk, SAE_PMK_LEN); 931 932 ret = 0; 933 fail: 934 crypto_bignum_deinit(tmp, 0); 935 return ret; 936 } 937 938 939 int sae_process_commit(struct sae_data *sae) 940 { 941 u8 k[SAE_MAX_PRIME_LEN]; 942 if (sae->tmp == NULL || 943 (sae->tmp->ec && sae_derive_k_ecc(sae, k) < 0) || 944 (sae->tmp->dh && sae_derive_k_ffc(sae, k) < 0) || 945 sae_derive_keys(sae, k) < 0) 946 return -1; 947 return 0; 948 } 949 950 951 void sae_write_commit(struct sae_data *sae, struct wpabuf *buf, 952 const struct wpabuf *token, const char *identifier) 953 { 954 u8 *pos; 955 956 if (sae->tmp == NULL) 957 return; 958 959 wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */ 960 if (token) { 961 wpabuf_put_buf(buf, token); 962 wpa_hexdump(MSG_DEBUG, "SAE: Anti-clogging token", 963 wpabuf_head(token), wpabuf_len(token)); 964 } 965 pos = wpabuf_put(buf, sae->tmp->prime_len); 966 crypto_bignum_to_bin(sae->tmp->own_commit_scalar, pos, 967 sae->tmp->prime_len, sae->tmp->prime_len); 968 wpa_hexdump(MSG_DEBUG, "SAE: own commit-scalar", 969 pos, sae->tmp->prime_len); 970 if (sae->tmp->ec) { 971 pos = wpabuf_put(buf, 2 * sae->tmp->prime_len); 972 crypto_ec_point_to_bin(sae->tmp->ec, 973 sae->tmp->own_commit_element_ecc, 974 pos, pos + sae->tmp->prime_len); 975 wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(x)", 976 pos, sae->tmp->prime_len); 977 wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(y)", 978 pos + sae->tmp->prime_len, sae->tmp->prime_len); 979 } else { 980 pos = wpabuf_put(buf, sae->tmp->prime_len); 981 crypto_bignum_to_bin(sae->tmp->own_commit_element_ffc, pos, 982 sae->tmp->prime_len, sae->tmp->prime_len); 983 wpa_hexdump(MSG_DEBUG, "SAE: own commit-element", 984 pos, sae->tmp->prime_len); 985 } 986 987 if (identifier) { 988 /* Password Identifier element */ 989 wpabuf_put_u8(buf, WLAN_EID_EXTENSION); 990 wpabuf_put_u8(buf, 1 + os_strlen(identifier)); 991 wpabuf_put_u8(buf, WLAN_EID_EXT_PASSWORD_IDENTIFIER); 992 wpabuf_put_str(buf, identifier); 993 wpa_printf(MSG_DEBUG, "SAE: own Password Identifier: %s", 994 identifier); 995 } 996 } 997 998 999 u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group) 1000 { 1001 if (allowed_groups) { 1002 int i; 1003 for (i = 0; allowed_groups[i] > 0; i++) { 1004 if (allowed_groups[i] == group) 1005 break; 1006 } 1007 if (allowed_groups[i] != group) { 1008 wpa_printf(MSG_DEBUG, "SAE: Proposed group %u not " 1009 "enabled in the current configuration", 1010 group); 1011 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; 1012 } 1013 } 1014 1015 if (sae->state == SAE_COMMITTED && group != sae->group) { 1016 wpa_printf(MSG_DEBUG, "SAE: Do not allow group to be changed"); 1017 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; 1018 } 1019 1020 if (group != sae->group && sae_set_group(sae, group) < 0) { 1021 wpa_printf(MSG_DEBUG, "SAE: Unsupported Finite Cyclic Group %u", 1022 group); 1023 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; 1024 } 1025 1026 if (sae->tmp == NULL) { 1027 wpa_printf(MSG_DEBUG, "SAE: Group information not yet initialized"); 1028 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1029 } 1030 1031 if (sae->tmp->dh && !allowed_groups) { 1032 wpa_printf(MSG_DEBUG, "SAE: Do not allow FFC group %u without " 1033 "explicit configuration enabling it", group); 1034 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; 1035 } 1036 1037 return WLAN_STATUS_SUCCESS; 1038 } 1039 1040 1041 static int sae_is_password_id_elem(const u8 *pos, const u8 *end) 1042 { 1043 return end - pos >= 3 && 1044 pos[0] == WLAN_EID_EXTENSION && 1045 pos[1] >= 1 && 1046 end - pos - 2 >= pos[1] && 1047 pos[2] == WLAN_EID_EXT_PASSWORD_IDENTIFIER; 1048 } 1049 1050 1051 static void sae_parse_commit_token(struct sae_data *sae, const u8 **pos, 1052 const u8 *end, const u8 **token, 1053 size_t *token_len) 1054 { 1055 size_t scalar_elem_len, tlen; 1056 const u8 *elem; 1057 1058 if (token) 1059 *token = NULL; 1060 if (token_len) 1061 *token_len = 0; 1062 1063 scalar_elem_len = (sae->tmp->ec ? 3 : 2) * sae->tmp->prime_len; 1064 if (scalar_elem_len >= (size_t) (end - *pos)) 1065 return; /* No extra data beyond peer scalar and element */ 1066 1067 /* It is a bit difficult to parse this now that there is an 1068 * optional variable length Anti-Clogging Token field and 1069 * optional variable length Password Identifier element in the 1070 * frame. We are sending out fixed length Anti-Clogging Token 1071 * fields, so use that length as a requirement for the received 1072 * token and check for the presence of possible Password 1073 * Identifier element based on the element header information. 1074 */ 1075 tlen = end - (*pos + scalar_elem_len); 1076 1077 if (tlen < SHA256_MAC_LEN) { 1078 wpa_printf(MSG_DEBUG, 1079 "SAE: Too short optional data (%u octets) to include our Anti-Clogging Token", 1080 (unsigned int) tlen); 1081 return; 1082 } 1083 1084 elem = *pos + scalar_elem_len; 1085 if (sae_is_password_id_elem(elem, end)) { 1086 /* Password Identifier element takes out all available 1087 * extra octets, so there can be no Anti-Clogging token in 1088 * this frame. */ 1089 return; 1090 } 1091 1092 elem += SHA256_MAC_LEN; 1093 if (sae_is_password_id_elem(elem, end)) { 1094 /* Password Identifier element is included in the end, so 1095 * remove its length from the Anti-Clogging token field. */ 1096 tlen -= 2 + elem[1]; 1097 } 1098 1099 wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token", *pos, tlen); 1100 if (token) 1101 *token = *pos; 1102 if (token_len) 1103 *token_len = tlen; 1104 *pos += tlen; 1105 } 1106 1107 1108 static u16 sae_parse_commit_scalar(struct sae_data *sae, const u8 **pos, 1109 const u8 *end) 1110 { 1111 struct crypto_bignum *peer_scalar; 1112 1113 if (sae->tmp->prime_len > end - *pos) { 1114 wpa_printf(MSG_DEBUG, "SAE: Not enough data for scalar"); 1115 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1116 } 1117 1118 peer_scalar = crypto_bignum_init_set(*pos, sae->tmp->prime_len); 1119 if (peer_scalar == NULL) 1120 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1121 1122 /* 1123 * IEEE Std 802.11-2012, 11.3.8.6.1: If there is a protocol instance for 1124 * the peer and it is in Authenticated state, the new Commit Message 1125 * shall be dropped if the peer-scalar is identical to the one used in 1126 * the existing protocol instance. 1127 */ 1128 if (sae->state == SAE_ACCEPTED && sae->peer_commit_scalar && 1129 crypto_bignum_cmp(sae->peer_commit_scalar, peer_scalar) == 0) { 1130 wpa_printf(MSG_DEBUG, "SAE: Do not accept re-use of previous " 1131 "peer-commit-scalar"); 1132 crypto_bignum_deinit(peer_scalar, 0); 1133 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1134 } 1135 1136 /* 1 < scalar < r */ 1137 if (crypto_bignum_is_zero(peer_scalar) || 1138 crypto_bignum_is_one(peer_scalar) || 1139 crypto_bignum_cmp(peer_scalar, sae->tmp->order) >= 0) { 1140 wpa_printf(MSG_DEBUG, "SAE: Invalid peer scalar"); 1141 crypto_bignum_deinit(peer_scalar, 0); 1142 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1143 } 1144 1145 1146 crypto_bignum_deinit(sae->peer_commit_scalar, 0); 1147 sae->peer_commit_scalar = peer_scalar; 1148 wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-scalar", 1149 *pos, sae->tmp->prime_len); 1150 *pos += sae->tmp->prime_len; 1151 1152 return WLAN_STATUS_SUCCESS; 1153 } 1154 1155 1156 static u16 sae_parse_commit_element_ecc(struct sae_data *sae, const u8 **pos, 1157 const u8 *end) 1158 { 1159 u8 prime[SAE_MAX_ECC_PRIME_LEN]; 1160 1161 if (2 * sae->tmp->prime_len > end - *pos) { 1162 wpa_printf(MSG_DEBUG, "SAE: Not enough data for " 1163 "commit-element"); 1164 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1165 } 1166 1167 if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime), 1168 sae->tmp->prime_len) < 0) 1169 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1170 1171 /* element x and y coordinates < p */ 1172 if (os_memcmp(*pos, prime, sae->tmp->prime_len) >= 0 || 1173 os_memcmp(*pos + sae->tmp->prime_len, prime, 1174 sae->tmp->prime_len) >= 0) { 1175 wpa_printf(MSG_DEBUG, "SAE: Invalid coordinates in peer " 1176 "element"); 1177 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1178 } 1179 1180 wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(x)", 1181 *pos, sae->tmp->prime_len); 1182 wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(y)", 1183 *pos + sae->tmp->prime_len, sae->tmp->prime_len); 1184 1185 crypto_ec_point_deinit(sae->tmp->peer_commit_element_ecc, 0); 1186 sae->tmp->peer_commit_element_ecc = 1187 crypto_ec_point_from_bin(sae->tmp->ec, *pos); 1188 if (sae->tmp->peer_commit_element_ecc == NULL) 1189 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1190 1191 if (!crypto_ec_point_is_on_curve(sae->tmp->ec, 1192 sae->tmp->peer_commit_element_ecc)) { 1193 wpa_printf(MSG_DEBUG, "SAE: Peer element is not on curve"); 1194 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1195 } 1196 1197 *pos += 2 * sae->tmp->prime_len; 1198 1199 return WLAN_STATUS_SUCCESS; 1200 } 1201 1202 1203 static u16 sae_parse_commit_element_ffc(struct sae_data *sae, const u8 **pos, 1204 const u8 *end) 1205 { 1206 struct crypto_bignum *res, *one; 1207 const u8 one_bin[1] = { 0x01 }; 1208 1209 if (sae->tmp->prime_len > end - *pos) { 1210 wpa_printf(MSG_DEBUG, "SAE: Not enough data for " 1211 "commit-element"); 1212 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1213 } 1214 wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element", *pos, 1215 sae->tmp->prime_len); 1216 1217 crypto_bignum_deinit(sae->tmp->peer_commit_element_ffc, 0); 1218 sae->tmp->peer_commit_element_ffc = 1219 crypto_bignum_init_set(*pos, sae->tmp->prime_len); 1220 if (sae->tmp->peer_commit_element_ffc == NULL) 1221 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1222 /* 1 < element < p - 1 */ 1223 res = crypto_bignum_init(); 1224 one = crypto_bignum_init_set(one_bin, sizeof(one_bin)); 1225 if (!res || !one || 1226 crypto_bignum_sub(sae->tmp->prime, one, res) || 1227 crypto_bignum_is_zero(sae->tmp->peer_commit_element_ffc) || 1228 crypto_bignum_is_one(sae->tmp->peer_commit_element_ffc) || 1229 crypto_bignum_cmp(sae->tmp->peer_commit_element_ffc, res) >= 0) { 1230 crypto_bignum_deinit(res, 0); 1231 crypto_bignum_deinit(one, 0); 1232 wpa_printf(MSG_DEBUG, "SAE: Invalid peer element"); 1233 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1234 } 1235 crypto_bignum_deinit(one, 0); 1236 1237 /* scalar-op(r, ELEMENT) = 1 modulo p */ 1238 if (crypto_bignum_exptmod(sae->tmp->peer_commit_element_ffc, 1239 sae->tmp->order, sae->tmp->prime, res) < 0 || 1240 !crypto_bignum_is_one(res)) { 1241 wpa_printf(MSG_DEBUG, "SAE: Invalid peer element (scalar-op)"); 1242 crypto_bignum_deinit(res, 0); 1243 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1244 } 1245 crypto_bignum_deinit(res, 0); 1246 1247 *pos += sae->tmp->prime_len; 1248 1249 return WLAN_STATUS_SUCCESS; 1250 } 1251 1252 1253 static u16 sae_parse_commit_element(struct sae_data *sae, const u8 **pos, 1254 const u8 *end) 1255 { 1256 if (sae->tmp->dh) 1257 return sae_parse_commit_element_ffc(sae, pos, end); 1258 return sae_parse_commit_element_ecc(sae, pos, end); 1259 } 1260 1261 1262 static int sae_parse_password_identifier(struct sae_data *sae, 1263 const u8 *pos, const u8 *end) 1264 { 1265 wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame", 1266 pos, end - pos); 1267 if (!sae_is_password_id_elem(pos, end)) { 1268 if (sae->tmp->pw_id) { 1269 wpa_printf(MSG_DEBUG, 1270 "SAE: No Password Identifier included, but expected one (%s)", 1271 sae->tmp->pw_id); 1272 return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER; 1273 } 1274 os_free(sae->tmp->pw_id); 1275 sae->tmp->pw_id = NULL; 1276 return WLAN_STATUS_SUCCESS; /* No Password Identifier */ 1277 } 1278 1279 if (sae->tmp->pw_id && 1280 (pos[1] - 1 != (int) os_strlen(sae->tmp->pw_id) || 1281 os_memcmp(sae->tmp->pw_id, pos + 3, pos[1] - 1) != 0)) { 1282 wpa_printf(MSG_DEBUG, 1283 "SAE: The included Password Identifier does not match the expected one (%s)", 1284 sae->tmp->pw_id); 1285 return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER; 1286 } 1287 1288 os_free(sae->tmp->pw_id); 1289 sae->tmp->pw_id = os_malloc(pos[1]); 1290 if (!sae->tmp->pw_id) 1291 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1292 os_memcpy(sae->tmp->pw_id, pos + 3, pos[1] - 1); 1293 sae->tmp->pw_id[pos[1] - 1] = '\0'; 1294 wpa_hexdump_ascii(MSG_DEBUG, "SAE: Received Password Identifier", 1295 sae->tmp->pw_id, pos[1] - 1); 1296 return WLAN_STATUS_SUCCESS; 1297 } 1298 1299 1300 u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len, 1301 const u8 **token, size_t *token_len, int *allowed_groups) 1302 { 1303 const u8 *pos = data, *end = data + len; 1304 u16 res; 1305 1306 /* Check Finite Cyclic Group */ 1307 if (end - pos < 2) 1308 return WLAN_STATUS_UNSPECIFIED_FAILURE; 1309 res = sae_group_allowed(sae, allowed_groups, WPA_GET_LE16(pos)); 1310 if (res != WLAN_STATUS_SUCCESS) 1311 return res; 1312 pos += 2; 1313 1314 /* Optional Anti-Clogging Token */ 1315 sae_parse_commit_token(sae, &pos, end, token, token_len); 1316 1317 /* commit-scalar */ 1318 res = sae_parse_commit_scalar(sae, &pos, end); 1319 if (res != WLAN_STATUS_SUCCESS) 1320 return res; 1321 1322 /* commit-element */ 1323 res = sae_parse_commit_element(sae, &pos, end); 1324 if (res != WLAN_STATUS_SUCCESS) 1325 return res; 1326 1327 /* Optional Password Identifier element */ 1328 res = sae_parse_password_identifier(sae, pos, end); 1329 if (res != WLAN_STATUS_SUCCESS) 1330 return res; 1331 1332 /* 1333 * Check whether peer-commit-scalar and PEER-COMMIT-ELEMENT are same as 1334 * the values we sent which would be evidence of a reflection attack. 1335 */ 1336 if (!sae->tmp->own_commit_scalar || 1337 crypto_bignum_cmp(sae->tmp->own_commit_scalar, 1338 sae->peer_commit_scalar) != 0 || 1339 (sae->tmp->dh && 1340 (!sae->tmp->own_commit_element_ffc || 1341 crypto_bignum_cmp(sae->tmp->own_commit_element_ffc, 1342 sae->tmp->peer_commit_element_ffc) != 0)) || 1343 (sae->tmp->ec && 1344 (!sae->tmp->own_commit_element_ecc || 1345 crypto_ec_point_cmp(sae->tmp->ec, 1346 sae->tmp->own_commit_element_ecc, 1347 sae->tmp->peer_commit_element_ecc) != 0))) 1348 return WLAN_STATUS_SUCCESS; /* scalars/elements are different */ 1349 1350 /* 1351 * This is a reflection attack - return special value to trigger caller 1352 * to silently discard the frame instead of replying with a specific 1353 * status code. 1354 */ 1355 return SAE_SILENTLY_DISCARD; 1356 } 1357 1358 1359 static void sae_cn_confirm(struct sae_data *sae, const u8 *sc, 1360 const struct crypto_bignum *scalar1, 1361 const u8 *element1, size_t element1_len, 1362 const struct crypto_bignum *scalar2, 1363 const u8 *element2, size_t element2_len, 1364 u8 *confirm) 1365 { 1366 const u8 *addr[5]; 1367 size_t len[5]; 1368 u8 scalar_b1[SAE_MAX_PRIME_LEN], scalar_b2[SAE_MAX_PRIME_LEN]; 1369 1370 /* Confirm 1371 * CN(key, X, Y, Z, ...) = 1372 * HMAC-SHA256(key, D2OS(X) || D2OS(Y) || D2OS(Z) | ...) 1373 * confirm = CN(KCK, send-confirm, commit-scalar, COMMIT-ELEMENT, 1374 * peer-commit-scalar, PEER-COMMIT-ELEMENT) 1375 * verifier = CN(KCK, peer-send-confirm, peer-commit-scalar, 1376 * PEER-COMMIT-ELEMENT, commit-scalar, COMMIT-ELEMENT) 1377 */ 1378 addr[0] = sc; 1379 len[0] = 2; 1380 crypto_bignum_to_bin(scalar1, scalar_b1, sizeof(scalar_b1), 1381 sae->tmp->prime_len); 1382 addr[1] = scalar_b1; 1383 len[1] = sae->tmp->prime_len; 1384 addr[2] = element1; 1385 len[2] = element1_len; 1386 crypto_bignum_to_bin(scalar2, scalar_b2, sizeof(scalar_b2), 1387 sae->tmp->prime_len); 1388 addr[3] = scalar_b2; 1389 len[3] = sae->tmp->prime_len; 1390 addr[4] = element2; 1391 len[4] = element2_len; 1392 hmac_sha256_vector(sae->tmp->kck, sizeof(sae->tmp->kck), 5, addr, len, 1393 confirm); 1394 } 1395 1396 1397 static void sae_cn_confirm_ecc(struct sae_data *sae, const u8 *sc, 1398 const struct crypto_bignum *scalar1, 1399 const struct crypto_ec_point *element1, 1400 const struct crypto_bignum *scalar2, 1401 const struct crypto_ec_point *element2, 1402 u8 *confirm) 1403 { 1404 u8 element_b1[2 * SAE_MAX_ECC_PRIME_LEN]; 1405 u8 element_b2[2 * SAE_MAX_ECC_PRIME_LEN]; 1406 1407 crypto_ec_point_to_bin(sae->tmp->ec, element1, element_b1, 1408 element_b1 + sae->tmp->prime_len); 1409 crypto_ec_point_to_bin(sae->tmp->ec, element2, element_b2, 1410 element_b2 + sae->tmp->prime_len); 1411 1412 sae_cn_confirm(sae, sc, scalar1, element_b1, 2 * sae->tmp->prime_len, 1413 scalar2, element_b2, 2 * sae->tmp->prime_len, confirm); 1414 } 1415 1416 1417 static void sae_cn_confirm_ffc(struct sae_data *sae, const u8 *sc, 1418 const struct crypto_bignum *scalar1, 1419 const struct crypto_bignum *element1, 1420 const struct crypto_bignum *scalar2, 1421 const struct crypto_bignum *element2, 1422 u8 *confirm) 1423 { 1424 u8 element_b1[SAE_MAX_PRIME_LEN]; 1425 u8 element_b2[SAE_MAX_PRIME_LEN]; 1426 1427 crypto_bignum_to_bin(element1, element_b1, sizeof(element_b1), 1428 sae->tmp->prime_len); 1429 crypto_bignum_to_bin(element2, element_b2, sizeof(element_b2), 1430 sae->tmp->prime_len); 1431 1432 sae_cn_confirm(sae, sc, scalar1, element_b1, sae->tmp->prime_len, 1433 scalar2, element_b2, sae->tmp->prime_len, confirm); 1434 } 1435 1436 1437 void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf) 1438 { 1439 const u8 *sc; 1440 1441 if (sae->tmp == NULL) 1442 return; 1443 1444 /* Send-Confirm */ 1445 sc = wpabuf_put(buf, 0); 1446 wpabuf_put_le16(buf, sae->send_confirm); 1447 if (sae->send_confirm < 0xffff) 1448 sae->send_confirm++; 1449 1450 if (sae->tmp->ec) 1451 sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar, 1452 sae->tmp->own_commit_element_ecc, 1453 sae->peer_commit_scalar, 1454 sae->tmp->peer_commit_element_ecc, 1455 wpabuf_put(buf, SHA256_MAC_LEN)); 1456 else 1457 sae_cn_confirm_ffc(sae, sc, sae->tmp->own_commit_scalar, 1458 sae->tmp->own_commit_element_ffc, 1459 sae->peer_commit_scalar, 1460 sae->tmp->peer_commit_element_ffc, 1461 wpabuf_put(buf, SHA256_MAC_LEN)); 1462 } 1463 1464 1465 int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len) 1466 { 1467 u8 verifier[SHA256_MAC_LEN]; 1468 1469 if (len < 2 + SHA256_MAC_LEN) { 1470 wpa_printf(MSG_DEBUG, "SAE: Too short confirm message"); 1471 return -1; 1472 } 1473 1474 wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", WPA_GET_LE16(data)); 1475 1476 if (!sae->tmp || !sae->peer_commit_scalar || 1477 !sae->tmp->own_commit_scalar) { 1478 wpa_printf(MSG_DEBUG, "SAE: Temporary data not yet available"); 1479 return -1; 1480 } 1481 1482 if (sae->tmp->ec) { 1483 if (!sae->tmp->peer_commit_element_ecc || 1484 !sae->tmp->own_commit_element_ecc) 1485 return -1; 1486 sae_cn_confirm_ecc(sae, data, sae->peer_commit_scalar, 1487 sae->tmp->peer_commit_element_ecc, 1488 sae->tmp->own_commit_scalar, 1489 sae->tmp->own_commit_element_ecc, 1490 verifier); 1491 } else { 1492 if (!sae->tmp->peer_commit_element_ffc || 1493 !sae->tmp->own_commit_element_ffc) 1494 return -1; 1495 sae_cn_confirm_ffc(sae, data, sae->peer_commit_scalar, 1496 sae->tmp->peer_commit_element_ffc, 1497 sae->tmp->own_commit_scalar, 1498 sae->tmp->own_commit_element_ffc, 1499 verifier); 1500 } 1501 1502 if (os_memcmp_const(verifier, data + 2, SHA256_MAC_LEN) != 0) { 1503 wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch"); 1504 wpa_hexdump(MSG_DEBUG, "SAE: Received confirm", 1505 data + 2, SHA256_MAC_LEN); 1506 wpa_hexdump(MSG_DEBUG, "SAE: Calculated verifier", 1507 verifier, SHA256_MAC_LEN); 1508 return -1; 1509 } 1510 1511 return 0; 1512 } 1513 1514 1515 const char * sae_state_txt(enum sae_state state) 1516 { 1517 switch (state) { 1518 case SAE_NOTHING: 1519 return "Nothing"; 1520 case SAE_COMMITTED: 1521 return "Committed"; 1522 case SAE_CONFIRMED: 1523 return "Confirmed"; 1524 case SAE_ACCEPTED: 1525 return "Accepted"; 1526 } 1527 return "?"; 1528 } 1529