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