2 * Simultaneous authentication of equals
3 * Copyright (c) 2012-2013, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
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"
20 int sae_set_group(struct sae_data *sae, int group)
24 /* First, check if this is an ECC group */
25 sae->ec = crypto_ec_init(group);
28 sae->prime_len = crypto_ec_prime_len(sae->ec);
29 sae->prime = crypto_ec_get_prime(sae->ec);
30 sae->order = crypto_ec_get_order(sae->ec);
34 /* Not an ECC group, check FFC */
35 sae->dh = dh_groups_get(group);
38 sae->prime_len = sae->dh->prime_len;
39 if (sae->prime_len > SAE_MAX_PRIME_LEN) {
44 sae->prime_buf = crypto_bignum_init_set(sae->dh->prime,
46 if (sae->prime_buf == NULL) {
50 sae->prime = sae->prime_buf;
52 sae->order_buf = crypto_bignum_init_set(sae->dh->order,
54 if (sae->order_buf == NULL) {
58 sae->order = sae->order_buf;
63 /* Unsupported group */
68 void sae_clear_data(struct sae_data *sae)
72 crypto_ec_deinit(sae->ec);
73 crypto_bignum_deinit(sae->prime_buf, 0);
74 crypto_bignum_deinit(sae->order_buf, 0);
75 crypto_bignum_deinit(sae->sae_rand, 1);
76 crypto_bignum_deinit(sae->pwe_ffc, 1);
77 crypto_bignum_deinit(sae->own_commit_scalar, 0);
78 crypto_bignum_deinit(sae->peer_commit_scalar, 0);
79 crypto_bignum_deinit(sae->own_commit_element_ffc, 0);
80 crypto_bignum_deinit(sae->peer_commit_element_ffc, 0);
81 crypto_ec_point_deinit(sae->pwe_ecc, 1);
82 crypto_ec_point_deinit(sae->own_commit_element_ecc, 0);
83 crypto_ec_point_deinit(sae->peer_commit_element_ecc, 0);
84 os_memset(sae, 0, sizeof(*sae));
88 static int val_one(const u8 *val, size_t len)
92 for (i = 0; i < len - 1; i++) {
97 return val[len - 1] == 1;
101 static int val_zero_or_one(const u8 *val, size_t len)
105 for (i = 0; i < len - 1; i++) {
110 return val[len - 1] <= 1;
114 static void buf_shift_right(u8 *buf, size_t len, size_t bits)
117 for (i = len - 1; i > 0; i--)
118 buf[i] = (buf[i - 1] << (8 - bits)) | (buf[i] >> bits);
123 static struct crypto_bignum * sae_get_rand(struct sae_data *sae)
125 u8 val[SAE_MAX_PRIME_LEN];
127 struct crypto_bignum *bn = NULL;
128 int order_len_bits = crypto_bignum_bits(sae->order);
129 size_t order_len = (order_len_bits + 7) / 8;
131 if (order_len > sizeof(val))
137 if (random_get_bytes(val, order_len) < 0)
139 if (order_len_bits % 8)
140 buf_shift_right(val, order_len, 8 - order_len_bits % 8);
141 if (val_zero_or_one(val, order_len))
143 bn = crypto_bignum_init_set(val, order_len);
146 if (crypto_bignum_cmp(bn, sae->order) >= 0)
151 os_memset(val, 0, order_len);
156 static struct crypto_bignum * sae_get_rand_and_mask(struct sae_data *sae)
158 crypto_bignum_deinit(sae->sae_rand, 1);
159 sae->sae_rand = sae_get_rand(sae);
160 if (sae->sae_rand == NULL)
162 return sae_get_rand(sae);
166 static void sae_pwd_seed_key(const u8 *addr1, const u8 *addr2, u8 *key)
168 wpa_printf(MSG_DEBUG, "SAE: PWE derivation - addr1=" MACSTR
169 " addr2=" MACSTR, MAC2STR(addr1), MAC2STR(addr2));
170 if (os_memcmp(addr1, addr2, ETH_ALEN) > 0) {
171 os_memcpy(key, addr1, ETH_ALEN);
172 os_memcpy(key + ETH_ALEN, addr2, ETH_ALEN);
174 os_memcpy(key, addr2, ETH_ALEN);
175 os_memcpy(key + ETH_ALEN, addr1, ETH_ALEN);
180 static int sae_test_pwd_seed(struct sae_data *sae, const u8 *pwd_seed,
181 struct crypto_ec_point *pwe)
183 u8 pwd_value[SAE_MAX_ECC_PRIME_LEN], prime[SAE_MAX_ECC_PRIME_LEN];
184 struct crypto_bignum *x;
188 if (crypto_bignum_to_bin(sae->prime, prime, sizeof(prime),
192 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
194 /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */
195 bits = crypto_ec_prime_len_bits(sae->ec);
196 sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking",
197 prime, sae->prime_len, pwd_value, bits);
199 buf_shift_right(pwd_value, sizeof(pwd_value), 8 - bits % 8);
200 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value",
201 pwd_value, sae->prime_len);
203 if (os_memcmp(pwd_value, prime, sae->prime_len) >= 0)
206 y_bit = pwd_seed[SHA256_MAC_LEN - 1] & 0x01;
208 x = crypto_bignum_init_set(pwd_value, sae->prime_len);
211 if (crypto_ec_point_solve_y_coord(sae->ec, pwe, x, y_bit) < 0) {
212 crypto_bignum_deinit(x, 0);
213 wpa_printf(MSG_DEBUG, "SAE: No solution found");
216 crypto_bignum_deinit(x, 0);
218 wpa_printf(MSG_DEBUG, "SAE: PWE found");
224 static int sae_derive_pwe(struct sae_data *sae, const u8 *addr1,
225 const u8 *addr2, const u8 *password,
229 u8 addrs[2 * ETH_ALEN];
233 struct crypto_ec_point *pwe_tmp;
235 if (sae->pwe_ecc == NULL) {
236 sae->pwe_ecc = crypto_ec_point_init(sae->ec);
237 if (sae->pwe_ecc == NULL)
240 pwe_tmp = crypto_ec_point_init(sae->ec);
244 wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
245 password, password_len);
248 * H(salt, ikm) = HMAC-SHA256(salt, ikm)
249 * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
250 * password || counter)
252 sae_pwd_seed_key(addr1, addr2, addrs);
255 len[0] = password_len;
257 len[1] = sizeof(counter);
260 * Continue for at least k iterations to protect against side-channel
261 * attacks that attempt to determine the number of iterations required
264 for (counter = 1; counter < k || !found; counter++) {
265 u8 pwd_seed[SHA256_MAC_LEN];
269 /* This should not happen in practice */
270 wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE");
274 wpa_printf(MSG_DEBUG, "SAE: counter = %u", counter);
275 if (hmac_sha256_vector(addrs, sizeof(addrs), 2, addr, len,
278 res = sae_test_pwd_seed(sae, pwd_seed,
279 found ? pwe_tmp : sae->pwe_ecc);
285 wpa_printf(MSG_DEBUG, "SAE: Ignore this PWE (one was "
286 "already selected)");
288 wpa_printf(MSG_DEBUG, "SAE: Use this PWE");
293 crypto_ec_point_deinit(pwe_tmp, 1);
295 return found ? 0 : -1;
299 static int sae_derive_commit(struct sae_data *sae)
301 struct crypto_bignum *mask;
304 mask = sae_get_rand_and_mask(sae);
306 wpa_printf(MSG_DEBUG, "SAE: Could not get rand/mask");
310 /* commit-scalar = (rand + mask) modulo r */
311 if (!sae->own_commit_scalar) {
312 sae->own_commit_scalar = crypto_bignum_init();
313 if (!sae->own_commit_scalar)
316 crypto_bignum_add(sae->sae_rand, mask, sae->own_commit_scalar);
317 crypto_bignum_mod(sae->own_commit_scalar, sae->order,
318 sae->own_commit_scalar);
320 /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */
321 if (!sae->own_commit_element_ecc) {
322 sae->own_commit_element_ecc = crypto_ec_point_init(sae->ec);
323 if (!sae->own_commit_element_ecc)
326 if (crypto_ec_point_mul(sae->ec, sae->pwe_ecc, mask,
327 sae->own_commit_element_ecc) < 0 ||
328 crypto_ec_point_invert(sae->ec, sae->own_commit_element_ecc) < 0) {
329 wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element");
335 crypto_bignum_deinit(mask, 1);
340 static int sae_prepare_commit_ec(const u8 *addr1, const u8 *addr2,
341 const u8 *password, size_t password_len,
342 struct sae_data *sae)
344 if (sae_derive_pwe(sae, addr1, addr2, password, password_len) < 0 ||
345 sae_derive_commit(sae) < 0)
351 static int sae_test_pwd_seed_dh(struct sae_data *sae, const u8 *pwd_seed,
352 struct crypto_bignum *pwe)
354 u8 pwd_value[SAE_MAX_PRIME_LEN], pwe_bin[SAE_MAX_PRIME_LEN];
355 size_t bits = sae->prime_len * 8;
357 struct crypto_bignum *a, *b;
360 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
362 /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */
363 sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking",
364 sae->dh->prime, sae->prime_len, pwd_value, bits);
366 buf_shift_right(pwd_value, sizeof(pwd_value), 8 - bits % 8);
367 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", pwd_value, sae->prime_len);
369 if (os_memcmp(pwd_value, sae->dh->prime, sae->prime_len) >= 0) {
370 wpa_printf(MSG_DEBUG, "SAE: pwd-value >= p");
374 /* PWE = pwd-value^((p-1)/r) modulo p */
376 a = crypto_bignum_init_set(pwd_value, sae->prime_len);
378 if (sae->dh->safe_prime) {
380 * r = (p-1)/2 for the group used here, so this becomes:
381 * PWE = pwd-value^2 modulo p
384 b = crypto_bignum_init_set(exp, sizeof(exp));
385 if (a == NULL || b == NULL)
388 res = crypto_bignum_exptmod(a, b, sae->prime, pwe);
390 struct crypto_bignum *tmp;
393 b = crypto_bignum_init_set(exp, sizeof(exp));
394 tmp = crypto_bignum_init();
395 if (a == NULL || b == NULL || tmp == NULL ||
396 crypto_bignum_sub(sae->prime, b, tmp) < 0 ||
397 crypto_bignum_div(tmp, sae->order, b) < 0)
400 res = crypto_bignum_exptmod(a, b, sae->prime, pwe);
401 crypto_bignum_deinit(tmp, 0);
404 crypto_bignum_deinit(a, 0);
405 crypto_bignum_deinit(b, 0);
408 wpa_printf(MSG_DEBUG, "SAE: Failed to calculate PWE");
412 res = crypto_bignum_to_bin(pwe, pwe_bin, sizeof(pwe_bin),
415 wpa_printf(MSG_DEBUG, "SAE: Not room for PWE");
418 wpa_hexdump_key(MSG_DEBUG, "SAE: PWE candidate", pwe_bin, res);
420 /* if (PWE > 1) --> found */
421 if (val_zero_or_one(pwe_bin, sae->prime_len)) {
422 wpa_printf(MSG_DEBUG, "SAE: PWE <= 1");
426 wpa_printf(MSG_DEBUG, "SAE: PWE found");
431 static int sae_derive_pwe_dh(struct sae_data *sae, const u8 *addr1,
432 const u8 *addr2, const u8 *password,
436 u8 addrs[2 * ETH_ALEN];
441 if (sae->pwe_ffc == NULL) {
442 sae->pwe_ffc = crypto_bignum_init();
443 if (sae->pwe_ffc == NULL)
447 wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
448 password, password_len);
451 * H(salt, ikm) = HMAC-SHA256(salt, ikm)
452 * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
453 * password || counter)
455 sae_pwd_seed_key(addr1, addr2, addrs);
458 len[0] = password_len;
460 len[1] = sizeof(counter);
462 for (counter = 1; !found; counter++) {
463 u8 pwd_seed[SHA256_MAC_LEN];
467 /* This should not happen in practice */
468 wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE");
472 wpa_printf(MSG_DEBUG, "SAE: counter = %u", counter);
473 if (hmac_sha256_vector(addrs, sizeof(addrs), 2, addr, len,
476 res = sae_test_pwd_seed_dh(sae, pwd_seed, sae->pwe_ffc);
480 wpa_printf(MSG_DEBUG, "SAE: Use this PWE");
485 return found ? 0 : -1;
489 static int sae_derive_commit_dh(struct sae_data *sae)
491 struct crypto_bignum *mask;
494 mask = sae_get_rand_and_mask(sae);
496 wpa_printf(MSG_DEBUG, "SAE: Could not get rand/mask");
500 /* commit-scalar = (rand + mask) modulo r */
501 if (!sae->own_commit_scalar) {
502 sae->own_commit_scalar = crypto_bignum_init();
503 if (!sae->own_commit_scalar)
506 crypto_bignum_add(sae->sae_rand, mask, sae->own_commit_scalar);
507 crypto_bignum_mod(sae->own_commit_scalar, sae->order,
508 sae->own_commit_scalar);
510 /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */
511 if (!sae->own_commit_element_ffc) {
512 sae->own_commit_element_ffc = crypto_bignum_init();
513 if (!sae->own_commit_element_ffc)
516 if (crypto_bignum_exptmod(sae->pwe_ffc, mask, sae->prime,
517 sae->own_commit_element_ffc) < 0 ||
518 crypto_bignum_inverse(sae->own_commit_element_ffc, sae->prime,
519 sae->own_commit_element_ffc) < 0) {
520 wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element");
526 crypto_bignum_deinit(mask, 1);
531 static int sae_prepare_commit_dh(const u8 *addr1, const u8 *addr2,
532 const u8 *password, size_t password_len,
533 struct sae_data *sae)
535 if (sae_derive_pwe_dh(sae, addr1, addr2, password, password_len) < 0 ||
536 sae_derive_commit_dh(sae) < 0)
542 int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
543 const u8 *password, size_t password_len,
544 struct sae_data *sae)
547 return sae_prepare_commit_ec(addr1, addr2, password,
552 return sae_prepare_commit_dh(addr1, addr2, password,
560 static int sae_derive_k_ec(struct sae_data *sae, u8 *k)
562 struct crypto_ec_point *K;
565 K = crypto_ec_point_init(sae->ec);
569 if (!crypto_ec_point_is_on_curve(sae->ec, sae->peer_commit_element_ecc))
571 wpa_printf(MSG_DEBUG, "SAE: Peer element is not on curve");
576 * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE),
577 * PEER-COMMIT-ELEMENT)))
578 * If K is identity element (point-at-infinity), reject
579 * k = F(K) (= x coordinate)
582 if (crypto_ec_point_mul(sae->ec, sae->pwe_ecc, sae->peer_commit_scalar,
584 crypto_ec_point_add(sae->ec, K, sae->peer_commit_element_ecc, K) < 0
586 crypto_ec_point_mul(sae->ec, K, sae->sae_rand, K) < 0 ||
587 crypto_ec_point_is_at_infinity(sae->ec, K) ||
588 crypto_ec_point_to_bin(sae->ec, K, k, NULL) < 0) {
589 wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k");
593 wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->prime_len);
597 crypto_ec_point_deinit(K, 1);
602 static int sae_derive_k_dh(struct sae_data *sae, u8 *k)
604 struct crypto_bignum *K;
607 K = crypto_bignum_init();
612 * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE),
613 * PEER-COMMIT-ELEMENT)))
614 * If K is identity element (one), reject.
615 * k = F(K) (= x coordinate)
618 if (crypto_bignum_exptmod(sae->pwe_ffc, sae->peer_commit_scalar,
619 sae->prime, K) < 0 ||
620 crypto_bignum_mulmod(K, sae->peer_commit_element_ffc, sae->prime, K)
622 crypto_bignum_exptmod(K, sae->sae_rand, sae->prime, K) < 0 ||
623 crypto_bignum_to_bin(K, k, SAE_MAX_PRIME_LEN, sae->prime_len) < 0 ||
624 val_one(k, sae->prime_len)) {
625 wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k");
629 wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->prime_len);
633 crypto_bignum_deinit(K, 1);
638 static int sae_derive_k(struct sae_data *sae, u8 *k)
641 return sae_derive_k_ec(sae, k);
642 return sae_derive_k_dh(sae, k);
646 static int sae_derive_keys(struct sae_data *sae, const u8 *k)
648 u8 null_key[SAE_KEYSEED_KEY_LEN], val[SAE_MAX_PRIME_LEN];
649 u8 keyseed[SHA256_MAC_LEN];
650 u8 keys[SAE_KCK_LEN + SAE_PMK_LEN];
651 struct crypto_bignum *tmp;
654 tmp = crypto_bignum_init();
658 /* keyseed = H(<0>32, k)
659 * KCK || PMK = KDF-512(keyseed, "SAE KCK and PMK",
660 * (commit-scalar + peer-commit-scalar) modulo r)
661 * PMKID = L((commit-scalar + peer-commit-scalar) modulo r, 0, 128)
664 os_memset(null_key, 0, sizeof(null_key));
665 hmac_sha256(null_key, sizeof(null_key), k, sae->prime_len, keyseed);
666 wpa_hexdump_key(MSG_DEBUG, "SAE: keyseed", keyseed, sizeof(keyseed));
668 crypto_bignum_add(sae->own_commit_scalar, sae->peer_commit_scalar, tmp);
669 crypto_bignum_mod(tmp, sae->order, tmp);
670 crypto_bignum_to_bin(tmp, val, sizeof(val), sae->prime_len);
671 wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN);
672 sha256_prf(keyseed, sizeof(keyseed), "SAE KCK and PMK",
673 val, sae->prime_len, keys, sizeof(keys));
674 os_memcpy(sae->kck, keys, SAE_KCK_LEN);
675 os_memcpy(sae->pmk, keys + SAE_KCK_LEN, SAE_PMK_LEN);
676 wpa_hexdump_key(MSG_DEBUG, "SAE: KCK", sae->kck, SAE_KCK_LEN);
677 wpa_hexdump_key(MSG_DEBUG, "SAE: PMK", sae->pmk, SAE_PMK_LEN);
681 crypto_bignum_deinit(tmp, 0);
686 int sae_process_commit(struct sae_data *sae)
688 u8 k[SAE_MAX_PRIME_LEN];
689 if (sae_derive_k(sae, k) < 0 || sae_derive_keys(sae, k) < 0)
695 void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
696 const struct wpabuf *token)
699 wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */
701 wpabuf_put_buf(buf, token);
702 pos = wpabuf_put(buf, sae->prime_len);
703 crypto_bignum_to_bin(sae->own_commit_scalar, pos, sae->prime_len,
705 wpa_hexdump(MSG_DEBUG, "SAE: own commit-scalar", pos, sae->prime_len);
707 pos = wpabuf_put(buf, 2 * sae->prime_len);
708 crypto_ec_point_to_bin(sae->ec, sae->own_commit_element_ecc,
709 pos, pos + sae->prime_len);
710 wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(x)",
711 pos, sae->prime_len);
712 wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(y)",
713 pos + sae->prime_len, sae->prime_len);
715 pos = wpabuf_put(buf, sae->prime_len);
716 crypto_bignum_to_bin(sae->own_commit_element_ffc, pos,
717 sae->prime_len, sae->prime_len);
718 wpa_hexdump(MSG_DEBUG, "SAE: own commit-element",
719 pos, sae->prime_len);
724 static u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups,
727 if (allowed_groups) {
729 for (i = 0; allowed_groups[i] >= 0; i++) {
730 if (allowed_groups[i] == group)
733 if (allowed_groups[i] != group) {
734 wpa_printf(MSG_DEBUG, "SAE: Proposed group %u not "
735 "enabled in the current configuration",
737 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
741 if (sae->state == SAE_COMMITTED && group != sae->group) {
742 wpa_printf(MSG_DEBUG, "SAE: Do not allow group to be changed");
743 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
746 if (group != sae->group && sae_set_group(sae, group) < 0) {
747 wpa_printf(MSG_DEBUG, "SAE: Unsupported Finite Cyclic Group %u",
749 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
752 if (sae->dh && !allowed_groups) {
753 wpa_printf(MSG_DEBUG, "SAE: Do not allow FFC group %u without "
754 "explicit configuration enabling it", group);
755 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
758 return WLAN_STATUS_SUCCESS;
762 static void sae_parse_commit_token(struct sae_data *sae, const u8 **pos,
763 const u8 *end, const u8 **token,
766 if (*pos + (sae->ec ? 3 : 2) * sae->prime_len < end) {
767 size_t tlen = end - (*pos + (sae->ec ? 3 : 2) * sae->prime_len);
768 wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token", *pos, tlen);
783 static u16 sae_parse_commit_scalar(struct sae_data *sae, const u8 **pos,
786 struct crypto_bignum *peer_scalar;
788 if (*pos + sae->prime_len > end) {
789 wpa_printf(MSG_DEBUG, "SAE: Not enough data for scalar");
790 return WLAN_STATUS_UNSPECIFIED_FAILURE;
793 peer_scalar = crypto_bignum_init_set(*pos, sae->prime_len);
794 if (peer_scalar == NULL)
795 return WLAN_STATUS_UNSPECIFIED_FAILURE;
798 * IEEE Std 802.11-2012, 11.3.8.6.1: If there is a protocol instance for
799 * the peer and it is in Authenticated state, the new Commit Message
800 * shall be dropped if the peer-scalar is identical to the one used in
801 * the existing protocol instance.
803 if (sae->state == SAE_ACCEPTED && sae->peer_commit_scalar &&
804 crypto_bignum_cmp(sae->peer_commit_scalar, peer_scalar) == 0) {
805 wpa_printf(MSG_DEBUG, "SAE: Do not accept re-use of previous "
806 "peer-commit-scalar");
807 crypto_bignum_deinit(peer_scalar, 0);
808 return WLAN_STATUS_UNSPECIFIED_FAILURE;
812 if (crypto_bignum_is_zero(peer_scalar) ||
813 crypto_bignum_cmp(peer_scalar, sae->order) >= 0) {
814 wpa_printf(MSG_DEBUG, "SAE: Invalid peer scalar");
815 crypto_bignum_deinit(peer_scalar, 0);
816 return WLAN_STATUS_UNSPECIFIED_FAILURE;
820 crypto_bignum_deinit(sae->peer_commit_scalar, 0);
821 sae->peer_commit_scalar = peer_scalar;
822 wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-scalar", *pos, sae->prime_len);
823 *pos += sae->prime_len;
825 return WLAN_STATUS_SUCCESS;
829 static u16 sae_parse_commit_element_ffc(struct sae_data *sae, const u8 *pos,
832 if (pos + sae->prime_len > end) {
833 wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
835 return WLAN_STATUS_UNSPECIFIED_FAILURE;
837 wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element", pos, sae->prime_len);
839 if (val_zero_or_one(pos, sae->prime_len)) {
840 wpa_printf(MSG_DEBUG, "SAE: Invalid peer element");
841 return WLAN_STATUS_UNSPECIFIED_FAILURE;
844 crypto_bignum_deinit(sae->peer_commit_element_ffc, 0);
845 sae->peer_commit_element_ffc = crypto_bignum_init_set(pos,
847 if (sae->peer_commit_element_ffc == NULL)
848 return WLAN_STATUS_UNSPECIFIED_FAILURE;
849 if (crypto_bignum_cmp(sae->peer_commit_element_ffc, sae->prime) >= 0) {
850 wpa_printf(MSG_DEBUG, "SAE: Invalid peer element");
851 return WLAN_STATUS_UNSPECIFIED_FAILURE;
854 return WLAN_STATUS_SUCCESS;
858 static u16 sae_parse_commit_element_ecc(struct sae_data *sae, const u8 *pos,
861 u8 prime[SAE_MAX_ECC_PRIME_LEN];
863 if (pos + 2 * sae->prime_len > end) {
864 wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
866 return WLAN_STATUS_UNSPECIFIED_FAILURE;
869 if (crypto_bignum_to_bin(sae->prime, prime, sizeof(prime),
871 return WLAN_STATUS_UNSPECIFIED_FAILURE;
873 /* element x and y coordinates < p */
874 if (os_memcmp(pos, prime, sae->prime_len) >= 0 ||
875 os_memcmp(pos + sae->prime_len + sae->prime_len, prime,
876 sae->prime_len) >= 0) {
877 wpa_printf(MSG_DEBUG, "SAE: Invalid coordinates in peer "
879 return WLAN_STATUS_UNSPECIFIED_FAILURE;
882 wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(x)",
883 pos, sae->prime_len);
884 wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(y)",
885 pos + sae->prime_len, sae->prime_len);
887 crypto_ec_point_deinit(sae->peer_commit_element_ecc, 0);
888 sae->peer_commit_element_ecc = crypto_ec_point_from_bin(sae->ec, pos);
889 if (sae->peer_commit_element_ecc == NULL)
890 return WLAN_STATUS_UNSPECIFIED_FAILURE;
892 return WLAN_STATUS_SUCCESS;
896 static u16 sae_parse_commit_element(struct sae_data *sae, const u8 *pos,
900 return sae_parse_commit_element_ffc(sae, pos, end);
901 return sae_parse_commit_element_ecc(sae, pos, end);
905 u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
906 const u8 **token, size_t *token_len, int *allowed_groups)
908 const u8 *pos = data, *end = data + len;
911 /* Check Finite Cyclic Group */
913 return WLAN_STATUS_UNSPECIFIED_FAILURE;
914 res = sae_group_allowed(sae, allowed_groups, WPA_GET_LE16(pos));
915 if (res != WLAN_STATUS_SUCCESS)
919 /* Optional Anti-Clogging Token */
920 sae_parse_commit_token(sae, &pos, end, token, token_len);
923 res = sae_parse_commit_scalar(sae, &pos, end);
924 if (res != WLAN_STATUS_SUCCESS)
928 return sae_parse_commit_element(sae, pos, end);
932 static void sae_cn_confirm(struct sae_data *sae, const u8 *sc,
933 const struct crypto_bignum *scalar1,
934 const u8 *element1, size_t element1_len,
935 const struct crypto_bignum *scalar2,
936 const u8 *element2, size_t element2_len,
941 u8 scalar_b1[SAE_MAX_PRIME_LEN], scalar_b2[SAE_MAX_PRIME_LEN];
944 * CN(key, X, Y, Z, ...) =
945 * HMAC-SHA256(key, D2OS(X) || D2OS(Y) || D2OS(Z) | ...)
946 * confirm = CN(KCK, send-confirm, commit-scalar, COMMIT-ELEMENT,
947 * peer-commit-scalar, PEER-COMMIT-ELEMENT)
948 * verifier = CN(KCK, peer-send-confirm, peer-commit-scalar,
949 * PEER-COMMIT-ELEMENT, commit-scalar, COMMIT-ELEMENT)
953 crypto_bignum_to_bin(scalar1, scalar_b1, sizeof(scalar_b1),
956 len[1] = sae->prime_len;
958 len[2] = element1_len;
959 crypto_bignum_to_bin(scalar2, scalar_b2, sizeof(scalar_b2),
962 len[3] = sae->prime_len;
964 len[4] = element2_len;
965 hmac_sha256_vector(sae->kck, sizeof(sae->kck), 5, addr, len, confirm);
969 static void sae_cn_confirm_ecc(struct sae_data *sae, const u8 *sc,
970 const struct crypto_bignum *scalar1,
971 const struct crypto_ec_point *element1,
972 const struct crypto_bignum *scalar2,
973 const struct crypto_ec_point *element2,
976 u8 element_b1[2 * SAE_MAX_ECC_PRIME_LEN];
977 u8 element_b2[2 * SAE_MAX_ECC_PRIME_LEN];
979 crypto_ec_point_to_bin(sae->ec, element1, element_b1,
980 element_b1 + sae->prime_len);
981 crypto_ec_point_to_bin(sae->ec, element2, element_b2,
982 element_b2 + sae->prime_len);
984 sae_cn_confirm(sae, sc, scalar1, element_b1, 2 * sae->prime_len,
985 scalar2, element_b2, 2 * sae->prime_len, confirm);
989 static void sae_cn_confirm_ffc(struct sae_data *sae, const u8 *sc,
990 const struct crypto_bignum *scalar1,
991 const struct crypto_bignum *element1,
992 const struct crypto_bignum *scalar2,
993 const struct crypto_bignum *element2,
996 u8 element_b1[SAE_MAX_PRIME_LEN];
997 u8 element_b2[SAE_MAX_PRIME_LEN];
999 crypto_bignum_to_bin(element1, element_b1, sizeof(element_b1),
1001 crypto_bignum_to_bin(element2, element_b2, sizeof(element_b2),
1004 sae_cn_confirm(sae, sc, scalar1, element_b1, sae->prime_len,
1005 scalar2, element_b2, sae->prime_len, confirm);
1009 void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
1014 sc = wpabuf_put(buf, 0);
1015 wpabuf_put_le16(buf, sae->send_confirm);
1016 sae->send_confirm++;
1019 sae_cn_confirm_ecc(sae, sc, sae->own_commit_scalar,
1020 sae->own_commit_element_ecc,
1021 sae->peer_commit_scalar,
1022 sae->peer_commit_element_ecc,
1023 wpabuf_put(buf, SHA256_MAC_LEN));
1025 sae_cn_confirm_ffc(sae, sc, sae->own_commit_scalar,
1026 sae->own_commit_element_ffc,
1027 sae->peer_commit_scalar,
1028 sae->peer_commit_element_ffc,
1029 wpabuf_put(buf, SHA256_MAC_LEN));
1033 int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
1035 u8 verifier[SHA256_MAC_LEN];
1037 if (len < 2 + SHA256_MAC_LEN) {
1038 wpa_printf(MSG_DEBUG, "SAE: Too short confirm message");
1042 wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", WPA_GET_LE16(data));
1045 sae_cn_confirm_ecc(sae, data, sae->peer_commit_scalar,
1046 sae->peer_commit_element_ecc,
1047 sae->own_commit_scalar,
1048 sae->own_commit_element_ecc,
1051 sae_cn_confirm_ffc(sae, data, sae->peer_commit_scalar,
1052 sae->peer_commit_element_ffc,
1053 sae->own_commit_scalar,
1054 sae->own_commit_element_ffc,
1057 if (os_memcmp(verifier, data + 2, SHA256_MAC_LEN) != 0) {
1058 wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch");
1059 wpa_hexdump(MSG_DEBUG, "SAE: Received confirm",
1060 data + 2, SHA256_MAC_LEN);
1061 wpa_hexdump(MSG_DEBUG, "SAE: Calculated verifier",
1062 verifier, SHA256_MAC_LEN);