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