1 /* 2 * Simultaneous authentication of equals 3 * Copyright (c) 2012-2013, 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 "crypto/crypto.h" 13 #include "crypto/sha256.h" 14 #include "crypto/random.h" 15 #include "crypto/dh_groups.h" 16 #include "ieee802_11_defs.h" 17 #include "sae.h" 18 19 20 int sae_set_group(struct sae_data *sae, int group) 21 { 22 struct sae_temporary_data *tmp; 23 24 sae_clear_data(sae); 25 tmp = sae->tmp = os_zalloc(sizeof(*tmp)); 26 if (tmp == NULL) 27 return -1; 28 29 /* First, check if this is an ECC group */ 30 tmp->ec = crypto_ec_init(group); 31 if (tmp->ec) { 32 sae->group = group; 33 tmp->prime_len = crypto_ec_prime_len(tmp->ec); 34 tmp->prime = crypto_ec_get_prime(tmp->ec); 35 tmp->order = crypto_ec_get_order(tmp->ec); 36 return 0; 37 } 38 39 /* Not an ECC group, check FFC */ 40 tmp->dh = dh_groups_get(group); 41 if (tmp->dh) { 42 sae->group = group; 43 tmp->prime_len = tmp->dh->prime_len; 44 if (tmp->prime_len > SAE_MAX_PRIME_LEN) { 45 sae_clear_data(sae); 46 return -1; 47 } 48 49 tmp->prime_buf = crypto_bignum_init_set(tmp->dh->prime, 50 tmp->prime_len); 51 if (tmp->prime_buf == NULL) { 52 sae_clear_data(sae); 53 return -1; 54 } 55 tmp->prime = tmp->prime_buf; 56 57 tmp->order_buf = crypto_bignum_init_set(tmp->dh->order, 58 tmp->dh->order_len); 59 if (tmp->order_buf == NULL) { 60 sae_clear_data(sae); 61 return -1; 62 } 63 tmp->order = tmp->order_buf; 64 65 return 0; 66 } 67 68 /* Unsupported group */ 69 return -1; 70 } 71 72 73 void sae_clear_temp_data(struct sae_data *sae) 74 { 75 struct sae_temporary_data *tmp; 76 if (sae == NULL || sae->tmp == NULL) 77 return; 78 tmp = sae->tmp; 79 crypto_ec_deinit(tmp->ec); 80 crypto_bignum_deinit(tmp->prime_buf, 0); 81 crypto_bignum_deinit(tmp->order_buf, 0); 82 crypto_bignum_deinit(tmp->sae_rand, 1); 83 crypto_bignum_deinit(tmp->pwe_ffc, 1); 84 crypto_bignum_deinit(tmp->own_commit_scalar, 0); 85 crypto_bignum_deinit(tmp->own_commit_element_ffc, 0); 86 crypto_bignum_deinit(tmp->peer_commit_element_ffc, 0); 87 crypto_ec_point_deinit(tmp->pwe_ecc, 1); 88 crypto_ec_point_deinit(tmp->own_commit_element_ecc, 0); 89 crypto_ec_point_deinit(tmp->peer_commit_element_ecc, 0); 90 wpabuf_free(tmp->anti_clogging_token); 91 bin_clear_free(tmp, sizeof(*tmp)); 92 sae->tmp = NULL; 93 } 94 95 96 void sae_clear_data(struct sae_data *sae) 97 { 98 if (sae == NULL) 99 return; 100 sae_clear_temp_data(sae); 101 crypto_bignum_deinit(sae->peer_commit_scalar, 0); 102 os_memset(sae, 0, sizeof(*sae)); 103 } 104 105 106 static void buf_shift_right(u8 *buf, size_t len, size_t bits) 107 { 108 size_t i; 109 for (i = len - 1; i > 0; i--) 110 buf[i] = (buf[i - 1] << (8 - bits)) | (buf[i] >> bits); 111 buf[0] >>= bits; 112 } 113 114 115 static struct crypto_bignum * sae_get_rand(struct sae_data *sae) 116 { 117 u8 val[SAE_MAX_PRIME_LEN]; 118 int iter = 0; 119 struct crypto_bignum *bn = NULL; 120 int order_len_bits = crypto_bignum_bits(sae->tmp->order); 121 size_t order_len = (order_len_bits + 7) / 8; 122 123 if (order_len > sizeof(val)) 124 return NULL; 125 126 for (;;) { 127 if (iter++ > 100) 128 return NULL; 129 if (random_get_bytes(val, order_len) < 0) 130 return NULL; 131 if (order_len_bits % 8) 132 buf_shift_right(val, order_len, 8 - order_len_bits % 8); 133 bn = crypto_bignum_init_set(val, order_len); 134 if (bn == NULL) 135 return NULL; 136 if (crypto_bignum_is_zero(bn) || 137 crypto_bignum_is_one(bn) || 138 crypto_bignum_cmp(bn, sae->tmp->order) >= 0) { 139 crypto_bignum_deinit(bn, 0); 140 continue; 141 } 142 break; 143 } 144 145 os_memset(val, 0, order_len); 146 return bn; 147 } 148 149 150 static struct crypto_bignum * sae_get_rand_and_mask(struct sae_data *sae) 151 { 152 crypto_bignum_deinit(sae->tmp->sae_rand, 1); 153 sae->tmp->sae_rand = sae_get_rand(sae); 154 if (sae->tmp->sae_rand == NULL) 155 return NULL; 156 return sae_get_rand(sae); 157 } 158 159 160 static void sae_pwd_seed_key(const u8 *addr1, const u8 *addr2, u8 *key) 161 { 162 wpa_printf(MSG_DEBUG, "SAE: PWE derivation - addr1=" MACSTR 163 " addr2=" MACSTR, MAC2STR(addr1), MAC2STR(addr2)); 164 if (os_memcmp(addr1, addr2, ETH_ALEN) > 0) { 165 os_memcpy(key, addr1, ETH_ALEN); 166 os_memcpy(key + ETH_ALEN, addr2, ETH_ALEN); 167 } else { 168 os_memcpy(key, addr2, ETH_ALEN); 169 os_memcpy(key + ETH_ALEN, addr1, ETH_ALEN); 170 } 171 } 172 173 174 static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed, 175 struct crypto_ec_point *pwe) 176 { 177 u8 pwd_value[SAE_MAX_ECC_PRIME_LEN], prime[SAE_MAX_ECC_PRIME_LEN]; 178 struct crypto_bignum *x; 179 int y_bit; 180 size_t bits; 181 182 if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime), 183 sae->tmp->prime_len) < 0) 184 return -1; 185 186 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN); 187 188 /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */ 189 bits = crypto_ec_prime_len_bits(sae->tmp->ec); 190 sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking", 191 prime, sae->tmp->prime_len, pwd_value, bits); 192 if (bits % 8) 193 buf_shift_right(pwd_value, sizeof(pwd_value), 8 - bits % 8); 194 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", 195 pwd_value, sae->tmp->prime_len); 196 197 if (os_memcmp(pwd_value, prime, sae->tmp->prime_len) >= 0) 198 return 0; 199 200 y_bit = pwd_seed[SHA256_MAC_LEN - 1] & 0x01; 201 202 x = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len); 203 if (x == NULL) 204 return -1; 205 if (crypto_ec_point_solve_y_coord(sae->tmp->ec, pwe, x, y_bit) < 0) { 206 crypto_bignum_deinit(x, 0); 207 wpa_printf(MSG_DEBUG, "SAE: No solution found"); 208 return 0; 209 } 210 crypto_bignum_deinit(x, 0); 211 212 wpa_printf(MSG_DEBUG, "SAE: PWE found"); 213 214 return 1; 215 } 216 217 218 static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed, 219 struct crypto_bignum *pwe) 220 { 221 u8 pwd_value[SAE_MAX_PRIME_LEN]; 222 size_t bits = sae->tmp->prime_len * 8; 223 u8 exp[1]; 224 struct crypto_bignum *a, *b; 225 int res; 226 227 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN); 228 229 /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */ 230 sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking", 231 sae->tmp->dh->prime, sae->tmp->prime_len, pwd_value, 232 bits); 233 if (bits % 8) 234 buf_shift_right(pwd_value, sizeof(pwd_value), 8 - bits % 8); 235 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", pwd_value, 236 sae->tmp->prime_len); 237 238 if (os_memcmp(pwd_value, sae->tmp->dh->prime, sae->tmp->prime_len) >= 0) 239 { 240 wpa_printf(MSG_DEBUG, "SAE: pwd-value >= p"); 241 return 0; 242 } 243 244 /* PWE = pwd-value^((p-1)/r) modulo p */ 245 246 a = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len); 247 248 if (sae->tmp->dh->safe_prime) { 249 /* 250 * r = (p-1)/2 for the group used here, so this becomes: 251 * PWE = pwd-value^2 modulo p 252 */ 253 exp[0] = 2; 254 b = crypto_bignum_init_set(exp, sizeof(exp)); 255 } else { 256 /* Calculate exponent: (p-1)/r */ 257 exp[0] = 1; 258 b = crypto_bignum_init_set(exp, sizeof(exp)); 259 if (b == NULL || 260 crypto_bignum_sub(sae->tmp->prime, b, b) < 0 || 261 crypto_bignum_div(b, sae->tmp->order, b) < 0) { 262 crypto_bignum_deinit(b, 0); 263 b = NULL; 264 } 265 } 266 267 if (a == NULL || b == NULL) 268 res = -1; 269 else 270 res = crypto_bignum_exptmod(a, b, sae->tmp->prime, pwe); 271 272 crypto_bignum_deinit(a, 0); 273 crypto_bignum_deinit(b, 0); 274 275 if (res < 0) { 276 wpa_printf(MSG_DEBUG, "SAE: Failed to calculate PWE"); 277 return -1; 278 } 279 280 /* if (PWE > 1) --> found */ 281 if (crypto_bignum_is_zero(pwe) || crypto_bignum_is_one(pwe)) { 282 wpa_printf(MSG_DEBUG, "SAE: PWE <= 1"); 283 return 0; 284 } 285 286 wpa_printf(MSG_DEBUG, "SAE: PWE found"); 287 return 1; 288 } 289 290 291 static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1, 292 const u8 *addr2, const u8 *password, 293 size_t password_len) 294 { 295 u8 counter, k = 4; 296 u8 addrs[2 * ETH_ALEN]; 297 const u8 *addr[2]; 298 size_t len[2]; 299 int found = 0; 300 struct crypto_ec_point *pwe_tmp; 301 302 if (sae->tmp->pwe_ecc == NULL) { 303 sae->tmp->pwe_ecc = crypto_ec_point_init(sae->tmp->ec); 304 if (sae->tmp->pwe_ecc == NULL) 305 return -1; 306 } 307 pwe_tmp = crypto_ec_point_init(sae->tmp->ec); 308 if (pwe_tmp == NULL) 309 return -1; 310 311 wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password", 312 password, password_len); 313 314 /* 315 * H(salt, ikm) = HMAC-SHA256(salt, ikm) 316 * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC), 317 * password || counter) 318 */ 319 sae_pwd_seed_key(addr1, addr2, addrs); 320 321 addr[0] = password; 322 len[0] = password_len; 323 addr[1] = &counter; 324 len[1] = sizeof(counter); 325 326 /* 327 * Continue for at least k iterations to protect against side-channel 328 * attacks that attempt to determine the number of iterations required 329 * in the loop. 330 */ 331 for (counter = 1; counter < k || !found; counter++) { 332 u8 pwd_seed[SHA256_MAC_LEN]; 333 int res; 334 335 if (counter > 200) { 336 /* This should not happen in practice */ 337 wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE"); 338 break; 339 } 340 341 wpa_printf(MSG_DEBUG, "SAE: counter = %u", counter); 342 if (hmac_sha256_vector(addrs, sizeof(addrs), 2, addr, len, 343 pwd_seed) < 0) 344 break; 345 res = sae_test_pwd_seed_ecc(sae, pwd_seed, 346 found ? pwe_tmp : 347 sae->tmp->pwe_ecc); 348 if (res < 0) 349 break; 350 if (res == 0) 351 continue; 352 if (found) { 353 wpa_printf(MSG_DEBUG, "SAE: Ignore this PWE (one was " 354 "already selected)"); 355 } else { 356 wpa_printf(MSG_DEBUG, "SAE: Use this PWE"); 357 found = 1; 358 } 359 } 360 361 crypto_ec_point_deinit(pwe_tmp, 1); 362 363 return found ? 0 : -1; 364 } 365 366 367 static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1, 368 const u8 *addr2, const u8 *password, 369 size_t password_len) 370 { 371 u8 counter; 372 u8 addrs[2 * ETH_ALEN]; 373 const u8 *addr[2]; 374 size_t len[2]; 375 int found = 0; 376 377 if (sae->tmp->pwe_ffc == NULL) { 378 sae->tmp->pwe_ffc = crypto_bignum_init(); 379 if (sae->tmp->pwe_ffc == NULL) 380 return -1; 381 } 382 383 wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password", 384 password, password_len); 385 386 /* 387 * H(salt, ikm) = HMAC-SHA256(salt, ikm) 388 * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC), 389 * password || counter) 390 */ 391 sae_pwd_seed_key(addr1, addr2, addrs); 392 393 addr[0] = password; 394 len[0] = password_len; 395 addr[1] = &counter; 396 len[1] = sizeof(counter); 397 398 for (counter = 1; !found; counter++) { 399 u8 pwd_seed[SHA256_MAC_LEN]; 400 int res; 401 402 if (counter > 200) { 403 /* This should not happen in practice */ 404 wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE"); 405 break; 406 } 407 408 wpa_printf(MSG_DEBUG, "SAE: counter = %u", counter); 409 if (hmac_sha256_vector(addrs, sizeof(addrs), 2, addr, len, 410 pwd_seed) < 0) 411 break; 412 res = sae_test_pwd_seed_ffc(sae, pwd_seed, sae->tmp->pwe_ffc); 413 if (res < 0) 414 break; 415 if (res > 0) { 416 wpa_printf(MSG_DEBUG, "SAE: Use this PWE"); 417 found = 1; 418 } 419 } 420 421 return found ? 0 : -1; 422 } 423 424 425 static int sae_derive_commit_element_ecc(struct sae_data *sae, 426 struct crypto_bignum *mask) 427 { 428 /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */ 429 if (!sae->tmp->own_commit_element_ecc) { 430 sae->tmp->own_commit_element_ecc = 431 crypto_ec_point_init(sae->tmp->ec); 432 if (!sae->tmp->own_commit_element_ecc) 433 return -1; 434 } 435 436 if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc, mask, 437 sae->tmp->own_commit_element_ecc) < 0 || 438 crypto_ec_point_invert(sae->tmp->ec, 439 sae->tmp->own_commit_element_ecc) < 0) { 440 wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element"); 441 return -1; 442 } 443 444 return 0; 445 } 446 447 448 static int sae_derive_commit_element_ffc(struct sae_data *sae, 449 struct crypto_bignum *mask) 450 { 451 /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */ 452 if (!sae->tmp->own_commit_element_ffc) { 453 sae->tmp->own_commit_element_ffc = crypto_bignum_init(); 454 if (!sae->tmp->own_commit_element_ffc) 455 return -1; 456 } 457 458 if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, mask, sae->tmp->prime, 459 sae->tmp->own_commit_element_ffc) < 0 || 460 crypto_bignum_inverse(sae->tmp->own_commit_element_ffc, 461 sae->tmp->prime, 462 sae->tmp->own_commit_element_ffc) < 0) { 463 wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element"); 464 return -1; 465 } 466 467 return 0; 468 } 469 470 471 static int sae_derive_commit(struct sae_data *sae) 472 { 473 struct crypto_bignum *mask; 474 int ret = -1; 475 476 mask = sae_get_rand_and_mask(sae); 477 if (mask == NULL) { 478 wpa_printf(MSG_DEBUG, "SAE: Could not get rand/mask"); 479 return -1; 480 } 481 482 /* commit-scalar = (rand + mask) modulo r */ 483 if (!sae->tmp->own_commit_scalar) { 484 sae->tmp->own_commit_scalar = crypto_bignum_init(); 485 if (!sae->tmp->own_commit_scalar) 486 goto fail; 487 } 488 crypto_bignum_add(sae->tmp->sae_rand, mask, 489 sae->tmp->own_commit_scalar); 490 crypto_bignum_mod(sae->tmp->own_commit_scalar, sae->tmp->order, 491 sae->tmp->own_commit_scalar); 492 493 if (sae->tmp->ec && sae_derive_commit_element_ecc(sae, mask) < 0) 494 goto fail; 495 if (sae->tmp->dh && sae_derive_commit_element_ffc(sae, mask) < 0) 496 goto fail; 497 498 ret = 0; 499 fail: 500 crypto_bignum_deinit(mask, 1); 501 return ret; 502 } 503 504 505 int sae_prepare_commit(const u8 *addr1, const u8 *addr2, 506 const u8 *password, size_t password_len, 507 struct sae_data *sae) 508 { 509 if (sae->tmp == NULL) 510 return -1; 511 if (sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password, 512 password_len) < 0) 513 return -1; 514 if (sae->tmp->dh && sae_derive_pwe_ffc(sae, addr1, addr2, password, 515 password_len) < 0) 516 return -1; 517 if (sae_derive_commit(sae) < 0) 518 return -1; 519 return 0; 520 } 521 522 523 static int sae_derive_k_ecc(struct sae_data *sae, u8 *k) 524 { 525 struct crypto_ec_point *K; 526 int ret = -1; 527 528 K = crypto_ec_point_init(sae->tmp->ec); 529 if (K == NULL) 530 goto fail; 531 532 /* 533 * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE), 534 * PEER-COMMIT-ELEMENT))) 535 * If K is identity element (point-at-infinity), reject 536 * k = F(K) (= x coordinate) 537 */ 538 539 if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc, 540 sae->peer_commit_scalar, K) < 0 || 541 crypto_ec_point_add(sae->tmp->ec, K, 542 sae->tmp->peer_commit_element_ecc, K) < 0 || 543 crypto_ec_point_mul(sae->tmp->ec, K, sae->tmp->sae_rand, K) < 0 || 544 crypto_ec_point_is_at_infinity(sae->tmp->ec, K) || 545 crypto_ec_point_to_bin(sae->tmp->ec, K, k, NULL) < 0) { 546 wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k"); 547 goto fail; 548 } 549 550 wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len); 551 552 ret = 0; 553 fail: 554 crypto_ec_point_deinit(K, 1); 555 return ret; 556 } 557 558 559 static int sae_derive_k_ffc(struct sae_data *sae, u8 *k) 560 { 561 struct crypto_bignum *K; 562 int ret = -1; 563 564 K = crypto_bignum_init(); 565 if (K == NULL) 566 goto fail; 567 568 /* 569 * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE), 570 * PEER-COMMIT-ELEMENT))) 571 * If K is identity element (one), reject. 572 * k = F(K) (= x coordinate) 573 */ 574 575 if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, sae->peer_commit_scalar, 576 sae->tmp->prime, K) < 0 || 577 crypto_bignum_mulmod(K, sae->tmp->peer_commit_element_ffc, 578 sae->tmp->prime, K) < 0 || 579 crypto_bignum_exptmod(K, sae->tmp->sae_rand, sae->tmp->prime, K) < 0 580 || 581 crypto_bignum_is_one(K) || 582 crypto_bignum_to_bin(K, k, SAE_MAX_PRIME_LEN, sae->tmp->prime_len) < 583 0) { 584 wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k"); 585 goto fail; 586 } 587 588 wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len); 589 590 ret = 0; 591 fail: 592 crypto_bignum_deinit(K, 1); 593 return ret; 594 } 595 596 597 static int sae_derive_keys(struct sae_data *sae, const u8 *k) 598 { 599 u8 null_key[SAE_KEYSEED_KEY_LEN], val[SAE_MAX_PRIME_LEN]; 600 u8 keyseed[SHA256_MAC_LEN]; 601 u8 keys[SAE_KCK_LEN + SAE_PMK_LEN]; 602 struct crypto_bignum *tmp; 603 int ret = -1; 604 605 tmp = crypto_bignum_init(); 606 if (tmp == NULL) 607 goto fail; 608 609 /* keyseed = H(<0>32, k) 610 * KCK || PMK = KDF-512(keyseed, "SAE KCK and PMK", 611 * (commit-scalar + peer-commit-scalar) modulo r) 612 * PMKID = L((commit-scalar + peer-commit-scalar) modulo r, 0, 128) 613 */ 614 615 os_memset(null_key, 0, sizeof(null_key)); 616 hmac_sha256(null_key, sizeof(null_key), k, sae->tmp->prime_len, 617 keyseed); 618 wpa_hexdump_key(MSG_DEBUG, "SAE: keyseed", keyseed, sizeof(keyseed)); 619 620 crypto_bignum_add(sae->tmp->own_commit_scalar, sae->peer_commit_scalar, 621 tmp); 622 crypto_bignum_mod(tmp, sae->tmp->order, tmp); 623 crypto_bignum_to_bin(tmp, val, sizeof(val), sae->tmp->prime_len); 624 wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN); 625 sha256_prf(keyseed, sizeof(keyseed), "SAE KCK and PMK", 626 val, sae->tmp->prime_len, keys, sizeof(keys)); 627 os_memset(keyseed, 0, sizeof(keyseed)); 628 os_memcpy(sae->tmp->kck, keys, SAE_KCK_LEN); 629 os_memcpy(sae->pmk, keys + SAE_KCK_LEN, SAE_PMK_LEN); 630 os_memset(keys, 0, sizeof(keys)); 631 wpa_hexdump_key(MSG_DEBUG, "SAE: KCK", sae->tmp->kck, SAE_KCK_LEN); 632 wpa_hexdump_key(MSG_DEBUG, "SAE: PMK", sae->pmk, SAE_PMK_LEN); 633 634 ret = 0; 635 fail: 636 crypto_bignum_deinit(tmp, 0); 637 return ret; 638 } 639 640 641 int sae_process_commit(struct sae_data *sae) 642 { 643 u8 k[SAE_MAX_PRIME_LEN]; 644 if (sae->tmp == NULL || 645 (sae->tmp->ec && sae_derive_k_ecc(sae, k) < 0) || 646 (sae->tmp->dh && sae_derive_k_ffc(sae, k) < 0) || 647 sae_derive_keys(sae, k) < 0) 648 return -1; 649 return 0; 650 } 651 652 653 void sae_write_commit(struct sae_data *sae, struct wpabuf *buf, 654 const struct wpabuf *token) 655 { 656 u8 *pos; 657 658 if (sae->tmp == NULL) 659 return; 660 661 wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */ 662 if (token) { 663 wpabuf_put_buf(buf, token); 664 wpa_hexdump(MSG_DEBUG, "SAE: Anti-clogging token", 665 wpabuf_head(token), wpabuf_len(token)); 666 } 667 pos = wpabuf_put(buf, sae->tmp->prime_len); 668 crypto_bignum_to_bin(sae->tmp->own_commit_scalar, pos, 669 sae->tmp->prime_len, sae->tmp->prime_len); 670 wpa_hexdump(MSG_DEBUG, "SAE: own commit-scalar", 671 pos, sae->tmp->prime_len); 672 if (sae->tmp->ec) { 673 pos = wpabuf_put(buf, 2 * sae->tmp->prime_len); 674 crypto_ec_point_to_bin(sae->tmp->ec, 675 sae->tmp->own_commit_element_ecc, 676 pos, pos + sae->tmp->prime_len); 677 wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(x)", 678 pos, sae->tmp->prime_len); 679 wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(y)", 680 pos + sae->tmp->prime_len, sae->tmp->prime_len); 681 } else { 682 pos = wpabuf_put(buf, sae->tmp->prime_len); 683 crypto_bignum_to_bin(sae->tmp->own_commit_element_ffc, pos, 684 sae->tmp->prime_len, sae->tmp->prime_len); 685 wpa_hexdump(MSG_DEBUG, "SAE: own commit-element", 686 pos, sae->tmp->prime_len); 687 } 688 } 689 690 691 u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group) 692 { 693 if (allowed_groups) { 694 int i; 695 for (i = 0; allowed_groups[i] > 0; i++) { 696 if (allowed_groups[i] == group) 697 break; 698 } 699 if (allowed_groups[i] != group) { 700 wpa_printf(MSG_DEBUG, "SAE: Proposed group %u not " 701 "enabled in the current configuration", 702 group); 703 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; 704 } 705 } 706 707 if (sae->state == SAE_COMMITTED && group != sae->group) { 708 wpa_printf(MSG_DEBUG, "SAE: Do not allow group to be changed"); 709 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; 710 } 711 712 if (group != sae->group && sae_set_group(sae, group) < 0) { 713 wpa_printf(MSG_DEBUG, "SAE: Unsupported Finite Cyclic Group %u", 714 group); 715 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; 716 } 717 718 if (sae->tmp == NULL) { 719 wpa_printf(MSG_DEBUG, "SAE: Group information not yet initialized"); 720 return WLAN_STATUS_UNSPECIFIED_FAILURE; 721 } 722 723 if (sae->tmp->dh && !allowed_groups) { 724 wpa_printf(MSG_DEBUG, "SAE: Do not allow FFC group %u without " 725 "explicit configuration enabling it", group); 726 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; 727 } 728 729 return WLAN_STATUS_SUCCESS; 730 } 731 732 733 static void sae_parse_commit_token(struct sae_data *sae, const u8 **pos, 734 const u8 *end, const u8 **token, 735 size_t *token_len) 736 { 737 if (*pos + (sae->tmp->ec ? 3 : 2) * sae->tmp->prime_len < end) { 738 size_t tlen = end - (*pos + (sae->tmp->ec ? 3 : 2) * 739 sae->tmp->prime_len); 740 wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token", *pos, tlen); 741 if (token) 742 *token = *pos; 743 if (token_len) 744 *token_len = tlen; 745 *pos += tlen; 746 } else { 747 if (token) 748 *token = NULL; 749 if (token_len) 750 *token_len = 0; 751 } 752 } 753 754 755 static u16 sae_parse_commit_scalar(struct sae_data *sae, const u8 **pos, 756 const u8 *end) 757 { 758 struct crypto_bignum *peer_scalar; 759 760 if (*pos + sae->tmp->prime_len > end) { 761 wpa_printf(MSG_DEBUG, "SAE: Not enough data for scalar"); 762 return WLAN_STATUS_UNSPECIFIED_FAILURE; 763 } 764 765 peer_scalar = crypto_bignum_init_set(*pos, sae->tmp->prime_len); 766 if (peer_scalar == NULL) 767 return WLAN_STATUS_UNSPECIFIED_FAILURE; 768 769 /* 770 * IEEE Std 802.11-2012, 11.3.8.6.1: If there is a protocol instance for 771 * the peer and it is in Authenticated state, the new Commit Message 772 * shall be dropped if the peer-scalar is identical to the one used in 773 * the existing protocol instance. 774 */ 775 if (sae->state == SAE_ACCEPTED && sae->peer_commit_scalar && 776 crypto_bignum_cmp(sae->peer_commit_scalar, peer_scalar) == 0) { 777 wpa_printf(MSG_DEBUG, "SAE: Do not accept re-use of previous " 778 "peer-commit-scalar"); 779 crypto_bignum_deinit(peer_scalar, 0); 780 return WLAN_STATUS_UNSPECIFIED_FAILURE; 781 } 782 783 /* 0 < scalar < r */ 784 if (crypto_bignum_is_zero(peer_scalar) || 785 crypto_bignum_cmp(peer_scalar, sae->tmp->order) >= 0) { 786 wpa_printf(MSG_DEBUG, "SAE: Invalid peer scalar"); 787 crypto_bignum_deinit(peer_scalar, 0); 788 return WLAN_STATUS_UNSPECIFIED_FAILURE; 789 } 790 791 792 crypto_bignum_deinit(sae->peer_commit_scalar, 0); 793 sae->peer_commit_scalar = peer_scalar; 794 wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-scalar", 795 *pos, sae->tmp->prime_len); 796 *pos += sae->tmp->prime_len; 797 798 return WLAN_STATUS_SUCCESS; 799 } 800 801 802 static u16 sae_parse_commit_element_ecc(struct sae_data *sae, const u8 *pos, 803 const u8 *end) 804 { 805 u8 prime[SAE_MAX_ECC_PRIME_LEN]; 806 807 if (pos + 2 * sae->tmp->prime_len > end) { 808 wpa_printf(MSG_DEBUG, "SAE: Not enough data for " 809 "commit-element"); 810 return WLAN_STATUS_UNSPECIFIED_FAILURE; 811 } 812 813 if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime), 814 sae->tmp->prime_len) < 0) 815 return WLAN_STATUS_UNSPECIFIED_FAILURE; 816 817 /* element x and y coordinates < p */ 818 if (os_memcmp(pos, prime, sae->tmp->prime_len) >= 0 || 819 os_memcmp(pos + sae->tmp->prime_len, prime, 820 sae->tmp->prime_len) >= 0) { 821 wpa_printf(MSG_DEBUG, "SAE: Invalid coordinates in peer " 822 "element"); 823 return WLAN_STATUS_UNSPECIFIED_FAILURE; 824 } 825 826 wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(x)", 827 pos, sae->tmp->prime_len); 828 wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(y)", 829 pos + sae->tmp->prime_len, sae->tmp->prime_len); 830 831 crypto_ec_point_deinit(sae->tmp->peer_commit_element_ecc, 0); 832 sae->tmp->peer_commit_element_ecc = 833 crypto_ec_point_from_bin(sae->tmp->ec, pos); 834 if (sae->tmp->peer_commit_element_ecc == NULL) 835 return WLAN_STATUS_UNSPECIFIED_FAILURE; 836 837 if (!crypto_ec_point_is_on_curve(sae->tmp->ec, 838 sae->tmp->peer_commit_element_ecc)) { 839 wpa_printf(MSG_DEBUG, "SAE: Peer element is not on curve"); 840 return WLAN_STATUS_UNSPECIFIED_FAILURE; 841 } 842 843 return WLAN_STATUS_SUCCESS; 844 } 845 846 847 static u16 sae_parse_commit_element_ffc(struct sae_data *sae, const u8 *pos, 848 const u8 *end) 849 { 850 struct crypto_bignum *res; 851 852 if (pos + sae->tmp->prime_len > end) { 853 wpa_printf(MSG_DEBUG, "SAE: Not enough data for " 854 "commit-element"); 855 return WLAN_STATUS_UNSPECIFIED_FAILURE; 856 } 857 wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element", pos, 858 sae->tmp->prime_len); 859 860 crypto_bignum_deinit(sae->tmp->peer_commit_element_ffc, 0); 861 sae->tmp->peer_commit_element_ffc = 862 crypto_bignum_init_set(pos, sae->tmp->prime_len); 863 if (sae->tmp->peer_commit_element_ffc == NULL) 864 return WLAN_STATUS_UNSPECIFIED_FAILURE; 865 if (crypto_bignum_is_zero(sae->tmp->peer_commit_element_ffc) || 866 crypto_bignum_is_one(sae->tmp->peer_commit_element_ffc) || 867 crypto_bignum_cmp(sae->tmp->peer_commit_element_ffc, 868 sae->tmp->prime) >= 0) { 869 wpa_printf(MSG_DEBUG, "SAE: Invalid peer element"); 870 return WLAN_STATUS_UNSPECIFIED_FAILURE; 871 } 872 873 /* scalar-op(r, ELEMENT) = 1 modulo p */ 874 res = crypto_bignum_init(); 875 if (res == NULL || 876 crypto_bignum_exptmod(sae->tmp->peer_commit_element_ffc, 877 sae->tmp->order, sae->tmp->prime, res) < 0 || 878 !crypto_bignum_is_one(res)) { 879 wpa_printf(MSG_DEBUG, "SAE: Invalid peer element (scalar-op)"); 880 crypto_bignum_deinit(res, 0); 881 return WLAN_STATUS_UNSPECIFIED_FAILURE; 882 } 883 crypto_bignum_deinit(res, 0); 884 885 return WLAN_STATUS_SUCCESS; 886 } 887 888 889 static u16 sae_parse_commit_element(struct sae_data *sae, const u8 *pos, 890 const u8 *end) 891 { 892 if (sae->tmp->dh) 893 return sae_parse_commit_element_ffc(sae, pos, end); 894 return sae_parse_commit_element_ecc(sae, pos, end); 895 } 896 897 898 u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len, 899 const u8 **token, size_t *token_len, int *allowed_groups) 900 { 901 const u8 *pos = data, *end = data + len; 902 u16 res; 903 904 /* Check Finite Cyclic Group */ 905 if (pos + 2 > end) 906 return WLAN_STATUS_UNSPECIFIED_FAILURE; 907 res = sae_group_allowed(sae, allowed_groups, WPA_GET_LE16(pos)); 908 if (res != WLAN_STATUS_SUCCESS) 909 return res; 910 pos += 2; 911 912 /* Optional Anti-Clogging Token */ 913 sae_parse_commit_token(sae, &pos, end, token, token_len); 914 915 /* commit-scalar */ 916 res = sae_parse_commit_scalar(sae, &pos, end); 917 if (res != WLAN_STATUS_SUCCESS) 918 return res; 919 920 /* commit-element */ 921 return sae_parse_commit_element(sae, pos, end); 922 } 923 924 925 static void sae_cn_confirm(struct sae_data *sae, const u8 *sc, 926 const struct crypto_bignum *scalar1, 927 const u8 *element1, size_t element1_len, 928 const struct crypto_bignum *scalar2, 929 const u8 *element2, size_t element2_len, 930 u8 *confirm) 931 { 932 const u8 *addr[5]; 933 size_t len[5]; 934 u8 scalar_b1[SAE_MAX_PRIME_LEN], scalar_b2[SAE_MAX_PRIME_LEN]; 935 936 /* Confirm 937 * CN(key, X, Y, Z, ...) = 938 * HMAC-SHA256(key, D2OS(X) || D2OS(Y) || D2OS(Z) | ...) 939 * confirm = CN(KCK, send-confirm, commit-scalar, COMMIT-ELEMENT, 940 * peer-commit-scalar, PEER-COMMIT-ELEMENT) 941 * verifier = CN(KCK, peer-send-confirm, peer-commit-scalar, 942 * PEER-COMMIT-ELEMENT, commit-scalar, COMMIT-ELEMENT) 943 */ 944 addr[0] = sc; 945 len[0] = 2; 946 crypto_bignum_to_bin(scalar1, scalar_b1, sizeof(scalar_b1), 947 sae->tmp->prime_len); 948 addr[1] = scalar_b1; 949 len[1] = sae->tmp->prime_len; 950 addr[2] = element1; 951 len[2] = element1_len; 952 crypto_bignum_to_bin(scalar2, scalar_b2, sizeof(scalar_b2), 953 sae->tmp->prime_len); 954 addr[3] = scalar_b2; 955 len[3] = sae->tmp->prime_len; 956 addr[4] = element2; 957 len[4] = element2_len; 958 hmac_sha256_vector(sae->tmp->kck, sizeof(sae->tmp->kck), 5, addr, len, 959 confirm); 960 } 961 962 963 static void sae_cn_confirm_ecc(struct sae_data *sae, const u8 *sc, 964 const struct crypto_bignum *scalar1, 965 const struct crypto_ec_point *element1, 966 const struct crypto_bignum *scalar2, 967 const struct crypto_ec_point *element2, 968 u8 *confirm) 969 { 970 u8 element_b1[2 * SAE_MAX_ECC_PRIME_LEN]; 971 u8 element_b2[2 * SAE_MAX_ECC_PRIME_LEN]; 972 973 crypto_ec_point_to_bin(sae->tmp->ec, element1, element_b1, 974 element_b1 + sae->tmp->prime_len); 975 crypto_ec_point_to_bin(sae->tmp->ec, element2, element_b2, 976 element_b2 + sae->tmp->prime_len); 977 978 sae_cn_confirm(sae, sc, scalar1, element_b1, 2 * sae->tmp->prime_len, 979 scalar2, element_b2, 2 * sae->tmp->prime_len, confirm); 980 } 981 982 983 static void sae_cn_confirm_ffc(struct sae_data *sae, const u8 *sc, 984 const struct crypto_bignum *scalar1, 985 const struct crypto_bignum *element1, 986 const struct crypto_bignum *scalar2, 987 const struct crypto_bignum *element2, 988 u8 *confirm) 989 { 990 u8 element_b1[SAE_MAX_PRIME_LEN]; 991 u8 element_b2[SAE_MAX_PRIME_LEN]; 992 993 crypto_bignum_to_bin(element1, element_b1, sizeof(element_b1), 994 sae->tmp->prime_len); 995 crypto_bignum_to_bin(element2, element_b2, sizeof(element_b2), 996 sae->tmp->prime_len); 997 998 sae_cn_confirm(sae, sc, scalar1, element_b1, sae->tmp->prime_len, 999 scalar2, element_b2, sae->tmp->prime_len, confirm); 1000 } 1001 1002 1003 void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf) 1004 { 1005 const u8 *sc; 1006 1007 if (sae->tmp == NULL) 1008 return; 1009 1010 /* Send-Confirm */ 1011 sc = wpabuf_put(buf, 0); 1012 wpabuf_put_le16(buf, sae->send_confirm); 1013 sae->send_confirm++; 1014 1015 if (sae->tmp->ec) 1016 sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar, 1017 sae->tmp->own_commit_element_ecc, 1018 sae->peer_commit_scalar, 1019 sae->tmp->peer_commit_element_ecc, 1020 wpabuf_put(buf, SHA256_MAC_LEN)); 1021 else 1022 sae_cn_confirm_ffc(sae, sc, sae->tmp->own_commit_scalar, 1023 sae->tmp->own_commit_element_ffc, 1024 sae->peer_commit_scalar, 1025 sae->tmp->peer_commit_element_ffc, 1026 wpabuf_put(buf, SHA256_MAC_LEN)); 1027 } 1028 1029 1030 int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len) 1031 { 1032 u8 verifier[SHA256_MAC_LEN]; 1033 1034 if (len < 2 + SHA256_MAC_LEN) { 1035 wpa_printf(MSG_DEBUG, "SAE: Too short confirm message"); 1036 return -1; 1037 } 1038 1039 wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", WPA_GET_LE16(data)); 1040 1041 if (sae->tmp == NULL) { 1042 wpa_printf(MSG_DEBUG, "SAE: Temporary data not yet available"); 1043 return -1; 1044 } 1045 1046 if (sae->tmp->ec) 1047 sae_cn_confirm_ecc(sae, data, sae->peer_commit_scalar, 1048 sae->tmp->peer_commit_element_ecc, 1049 sae->tmp->own_commit_scalar, 1050 sae->tmp->own_commit_element_ecc, 1051 verifier); 1052 else 1053 sae_cn_confirm_ffc(sae, data, sae->peer_commit_scalar, 1054 sae->tmp->peer_commit_element_ffc, 1055 sae->tmp->own_commit_scalar, 1056 sae->tmp->own_commit_element_ffc, 1057 verifier); 1058 1059 if (os_memcmp_const(verifier, data + 2, SHA256_MAC_LEN) != 0) { 1060 wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch"); 1061 wpa_hexdump(MSG_DEBUG, "SAE: Received confirm", 1062 data + 2, SHA256_MAC_LEN); 1063 wpa_hexdump(MSG_DEBUG, "SAE: Calculated verifier", 1064 verifier, SHA256_MAC_LEN); 1065 return -1; 1066 } 1067 1068 return 0; 1069 } 1070