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 /* Assume r = (p-1)/2 for this group */
54 sae->order_buf = crypto_bignum_init();
55 if (sae->order_buf == NULL ||
56 crypto_bignum_rshift(sae->prime, 1, sae->order_buf) < 0) {
60 sae->order = sae->order_buf;
65 /* Unsupported group */
70 void sae_clear_data(struct sae_data *sae)
74 crypto_ec_deinit(sae->ec);
75 crypto_bignum_deinit(sae->prime_buf, 0);
76 crypto_bignum_deinit(sae->order_buf, 0);
77 os_memset(sae, 0, sizeof(*sae));
81 static int val_one(const u8 *val, size_t len)
85 for (i = 0; i < len - 1; i++) {
90 return val[len - 1] == 1;
94 static int val_zero_or_one(const u8 *val, size_t len)
98 for (i = 0; i < len - 1; i++) {
103 return val[len - 1] <= 1;
107 static int val_zero(const u8 *val, size_t len)
110 for (i = 0; i < len; i++) {
118 static void buf_shift_right(u8 *buf, size_t len, size_t bits)
121 for (i = len - 1; i > 0; i--)
122 buf[i] = (buf[i - 1] << (8 - bits)) | (buf[i] >> bits);
127 static int sae_get_rand(const u8 *order, size_t prime_len_bits, u8 *val)
130 size_t prime_len = (prime_len_bits + 7) / 8;
135 if (random_get_bytes(val, prime_len) < 0)
137 if (prime_len_bits % 8)
138 buf_shift_right(val, prime_len, 8 - prime_len_bits % 8);
139 } while (os_memcmp(val, order, prime_len) >= 0 ||
140 val_zero_or_one(val, prime_len));
146 static struct crypto_bignum * sae_get_rand_and_mask(struct sae_data *sae)
148 u8 mask[SAE_MAX_PRIME_LEN], order[SAE_MAX_PRIME_LEN];
149 struct crypto_bignum *bn;
150 size_t prime_len_bits = crypto_ec_prime_len_bits(sae->ec);
152 if (crypto_bignum_to_bin(sae->order, order, sizeof(order),
156 if (sae_get_rand(order, prime_len_bits, sae->sae_rand) < 0 ||
157 sae_get_rand(order, prime_len_bits, mask) < 0)
159 wpa_hexdump_key(MSG_DEBUG, "SAE: rand",
160 sae->sae_rand, sae->prime_len);
161 wpa_hexdump_key(MSG_DEBUG, "SAE: mask", mask, sae->prime_len);
162 bn = crypto_bignum_init_set(mask, sae->prime_len);
163 os_memset(mask, 0, sizeof(mask));
168 static struct crypto_bignum * sae_get_rand_and_mask_dh(struct sae_data *sae)
170 u8 mask[SAE_MAX_PRIME_LEN], order[SAE_MAX_PRIME_LEN];
171 struct crypto_bignum *bn;
172 size_t prime_len_bits = sae->prime_len * 8;
174 if (crypto_bignum_to_bin(sae->order, order, sizeof(order),
175 sae->prime_len) < 0 ||
176 sae_get_rand(order, prime_len_bits, sae->sae_rand) < 0 ||
177 sae_get_rand(order, prime_len_bits, mask) < 0)
180 wpa_hexdump_key(MSG_DEBUG, "SAE: rand",
181 sae->sae_rand, sae->prime_len);
182 wpa_hexdump_key(MSG_DEBUG, "SAE: mask", mask, sae->prime_len);
183 bn = crypto_bignum_init_set(mask, sae->prime_len);
184 os_memset(mask, 0, sizeof(mask));
189 static void sae_pwd_seed_key(const u8 *addr1, const u8 *addr2, u8 *key)
191 wpa_printf(MSG_DEBUG, "SAE: PWE derivation - addr1=" MACSTR
192 " addr2=" MACSTR, MAC2STR(addr1), MAC2STR(addr2));
193 if (os_memcmp(addr1, addr2, ETH_ALEN) > 0) {
194 os_memcpy(key, addr1, ETH_ALEN);
195 os_memcpy(key + ETH_ALEN, addr2, ETH_ALEN);
197 os_memcpy(key, addr2, ETH_ALEN);
198 os_memcpy(key + ETH_ALEN, addr1, ETH_ALEN);
203 static int sae_test_pwd_seed(struct sae_data *sae, const u8 *pwd_seed,
204 struct crypto_ec_point *pwe, u8 *pwe_bin)
206 u8 pwd_value[SAE_MAX_PRIME_LEN], prime[SAE_MAX_PRIME_LEN];
207 struct crypto_bignum *x;
211 if (crypto_bignum_to_bin(sae->prime, prime, sizeof(prime),
215 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
217 /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */
218 bits = crypto_ec_prime_len_bits(sae->ec);
219 sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking",
220 prime, sae->prime_len, pwd_value, bits);
222 buf_shift_right(pwd_value, sizeof(pwd_value), 8 - bits % 8);
223 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value",
224 pwd_value, sae->prime_len);
226 if (os_memcmp(pwd_value, prime, sae->prime_len) >= 0)
229 y_bit = pwd_seed[SHA256_MAC_LEN - 1] & 0x01;
231 x = crypto_bignum_init_set(pwd_value, sae->prime_len);
234 if (crypto_ec_point_solve_y_coord(sae->ec, pwe, x, y_bit) < 0) {
235 crypto_bignum_deinit(x, 0);
236 wpa_printf(MSG_DEBUG, "SAE: No solution found");
239 crypto_bignum_deinit(x, 0);
241 wpa_printf(MSG_DEBUG, "SAE: PWE found");
243 if (crypto_ec_point_to_bin(sae->ec, pwe, pwe_bin,
244 pwe_bin + sae->prime_len) < 0)
247 wpa_hexdump_key(MSG_DEBUG, "SAE: PWE x", pwe_bin, sae->prime_len);
248 wpa_hexdump_key(MSG_DEBUG, "SAE: PWE y",
249 pwe_bin + sae->prime_len, sae->prime_len);
254 static int sae_derive_pwe(struct sae_data *sae, const u8 *addr1,
255 const u8 *addr2, const u8 *password,
256 size_t password_len, struct crypto_ec_point *pwe,
260 u8 addrs[2 * ETH_ALEN];
264 struct crypto_ec_point *pwe_tmp;
265 u8 pwe_bin_tmp[2 * SAE_MAX_PRIME_LEN];
267 pwe_tmp = crypto_ec_point_init(sae->ec);
271 wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
272 password, password_len);
275 * H(salt, ikm) = HMAC-SHA256(salt, ikm)
276 * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
277 * password || counter)
279 sae_pwd_seed_key(addr1, addr2, addrs);
282 len[0] = password_len;
284 len[1] = sizeof(counter);
287 * Continue for at least k iterations to protect against side-channel
288 * attacks that attempt to determine the number of iterations required
291 for (counter = 1; counter < k || !found; counter++) {
292 u8 pwd_seed[SHA256_MAC_LEN];
296 /* This should not happen in practice */
297 wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE");
301 wpa_printf(MSG_DEBUG, "SAE: counter = %u", counter);
302 if (hmac_sha256_vector(addrs, sizeof(addrs), 2, addr, len,
305 res = sae_test_pwd_seed(sae, pwd_seed,
306 found ? pwe_tmp : pwe,
307 found ? pwe_bin_tmp : pwe_bin);
313 wpa_printf(MSG_DEBUG, "SAE: Ignore this PWE (one was "
314 "already selected)");
316 wpa_printf(MSG_DEBUG, "SAE: Use this PWE");
321 crypto_ec_point_deinit(pwe_tmp, 1);
323 return found ? 0 : -1;
327 static int sae_derive_commit(struct sae_data *sae, struct crypto_ec_point *pwe)
329 struct crypto_bignum *x, *bn_rand, *mask;
330 struct crypto_ec_point *elem;
333 mask = sae_get_rand_and_mask(sae);
335 wpa_printf(MSG_DEBUG, "SAE: Could not get rand/mask");
339 x = crypto_bignum_init();
340 bn_rand = crypto_bignum_init_set(sae->sae_rand, sae->prime_len);
341 elem = crypto_ec_point_init(sae->ec);
342 if (x == NULL || bn_rand == NULL || elem == NULL)
345 /* commit-scalar = (rand + mask) modulo r */
346 crypto_bignum_add(bn_rand, mask, x);
347 crypto_bignum_mod(x, sae->order, x);
348 crypto_bignum_to_bin(x, sae->own_commit_scalar,
349 sizeof(sae->own_commit_scalar), sae->prime_len);
350 wpa_hexdump(MSG_DEBUG, "SAE: commit-scalar",
351 sae->own_commit_scalar, sae->prime_len);
353 /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */
354 if (crypto_ec_point_mul(sae->ec, pwe, mask, elem) < 0 ||
355 crypto_ec_point_invert(sae->ec, elem) < 0 ||
356 crypto_ec_point_to_bin(sae->ec, elem, sae->own_commit_element,
357 sae->own_commit_element + sae->prime_len) <
359 wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element");
363 wpa_hexdump(MSG_DEBUG, "SAE: commit-element x",
364 sae->own_commit_element, sae->prime_len);
365 wpa_hexdump(MSG_DEBUG, "SAE: commit-element y",
366 sae->own_commit_element + sae->prime_len, sae->prime_len);
370 crypto_ec_point_deinit(elem, 0);
371 crypto_bignum_deinit(mask, 1);
372 crypto_bignum_deinit(bn_rand, 1);
373 crypto_bignum_deinit(x, 1);
378 static int sae_prepare_commit_ec(const u8 *addr1, const u8 *addr2,
379 const u8 *password, size_t password_len,
380 struct sae_data *sae)
382 struct crypto_ec_point *pwe;
385 pwe = crypto_ec_point_init(sae->ec);
387 sae_derive_pwe(sae, addr1, addr2, password, password_len, pwe,
389 sae_derive_commit(sae, pwe) < 0)
392 crypto_ec_point_deinit(pwe, 1);
398 static int sae_test_pwd_seed_dh(struct sae_data *sae, const u8 *pwd_seed,
399 struct crypto_bignum *pwe)
401 u8 pwd_value[SAE_MAX_PRIME_LEN];
402 size_t bits = sae->prime_len * 8;
404 struct crypto_bignum *a, *b;
407 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
409 /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */
410 sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking",
411 sae->dh->prime, sae->prime_len, pwd_value, bits);
413 buf_shift_right(pwd_value, sizeof(pwd_value), 8 - bits % 8);
414 wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", pwd_value, sae->prime_len);
416 if (os_memcmp(pwd_value, sae->dh->prime, sae->prime_len) >= 0) {
417 wpa_printf(MSG_DEBUG, "SAE: pwd-value >= p");
421 /* PWE = pwd-value^((p-1)/r) modulo p */
423 a = crypto_bignum_init_set(pwd_value, sae->prime_len);
425 if (sae->safe_prime) {
427 * r = (p-1)/2 for the group used here, so this becomes:
428 * PWE = pwd-value^2 modulo p
431 b = crypto_bignum_init_set(exp, sizeof(exp));
432 if (a == NULL || b == NULL)
435 res = crypto_bignum_exptmod(a, b, sae->prime, pwe);
437 struct crypto_bignum *tmp;
440 b = crypto_bignum_init_set(exp, sizeof(exp));
441 tmp = crypto_bignum_init();
442 if (a == NULL || b == NULL || tmp == NULL ||
443 crypto_bignum_sub(sae->prime, b, tmp) < 0 ||
444 crypto_bignum_div(tmp, sae->order, b) < 0)
447 res = crypto_bignum_exptmod(a, b, sae->prime, pwe);
448 crypto_bignum_deinit(tmp, 0);
451 crypto_bignum_deinit(a, 0);
452 crypto_bignum_deinit(b, 0);
455 wpa_printf(MSG_DEBUG, "SAE: Failed to calculate PWE");
459 res = crypto_bignum_to_bin(pwe, sae->pwe, sizeof(sae->pwe),
462 wpa_printf(MSG_DEBUG, "SAE: Not room for PWE");
465 wpa_hexdump_key(MSG_DEBUG, "SAE: PWE candidate", sae->pwe, res);
467 /* if (PWE > 1) --> found */
468 if (val_zero_or_one(sae->pwe, sae->prime_len)) {
469 wpa_printf(MSG_DEBUG, "SAE: PWE <= 1");
473 wpa_printf(MSG_DEBUG, "SAE: PWE found");
478 static int sae_derive_pwe_dh(struct sae_data *sae, const u8 *addr1,
479 const u8 *addr2, const u8 *password,
480 size_t password_len, struct crypto_bignum *pwe)
483 u8 addrs[2 * ETH_ALEN];
488 wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
489 password, password_len);
492 * H(salt, ikm) = HMAC-SHA256(salt, ikm)
493 * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
494 * password || counter)
496 sae_pwd_seed_key(addr1, addr2, addrs);
499 len[0] = password_len;
501 len[1] = sizeof(counter);
503 for (counter = 1; !found; counter++) {
504 u8 pwd_seed[SHA256_MAC_LEN];
508 /* This should not happen in practice */
509 wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE");
513 wpa_printf(MSG_DEBUG, "SAE: counter = %u", counter);
514 if (hmac_sha256_vector(addrs, sizeof(addrs), 2, addr, len,
517 res = sae_test_pwd_seed_dh(sae, pwd_seed, pwe);
521 wpa_printf(MSG_DEBUG, "SAE: Use this PWE");
526 return found ? 0 : -1;
530 static int sae_derive_commit_dh(struct sae_data *sae, struct crypto_bignum *pwe)
532 struct crypto_bignum *x, *bn_rand, *mask, *elem;
535 mask = sae_get_rand_and_mask_dh(sae);
537 wpa_printf(MSG_DEBUG, "SAE: Could not get rand/mask");
541 x = crypto_bignum_init();
542 bn_rand = crypto_bignum_init_set(sae->sae_rand, sae->prime_len);
543 elem = crypto_bignum_init();
544 if (x == NULL || bn_rand == NULL || elem == NULL)
547 /* commit-scalar = (rand + mask) modulo r */
548 crypto_bignum_add(bn_rand, mask, x);
549 crypto_bignum_mod(x, sae->order, x);
550 crypto_bignum_to_bin(x, sae->own_commit_scalar,
551 sizeof(sae->own_commit_scalar), sae->prime_len);
552 wpa_hexdump(MSG_DEBUG, "SAE: commit-scalar",
553 sae->own_commit_scalar, sae->prime_len);
555 /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */
556 if (crypto_bignum_exptmod(pwe, mask, sae->prime, elem) < 0 ||
557 crypto_bignum_inverse(elem, sae->prime, elem) < 0 ||
558 crypto_bignum_to_bin(elem, sae->own_commit_element,
559 sizeof(sae->own_commit_element),
560 sae->prime_len) < 0) {
561 wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element");
565 wpa_hexdump(MSG_DEBUG, "SAE: commit-element",
566 sae->own_commit_element, sae->prime_len);
570 crypto_bignum_deinit(elem, 0);
571 crypto_bignum_deinit(mask, 1);
572 crypto_bignum_deinit(bn_rand, 1);
573 crypto_bignum_deinit(x, 1);
578 static int sae_prepare_commit_dh(const u8 *addr1, const u8 *addr2,
579 const u8 *password, size_t password_len,
580 struct sae_data *sae)
582 struct crypto_bignum *pwe;
585 pwe = crypto_bignum_init();
587 sae_derive_pwe_dh(sae, addr1, addr2, password, password_len, pwe) <
589 sae_derive_commit_dh(sae, pwe) < 0)
592 crypto_bignum_deinit(pwe, 1);
598 int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
599 const u8 *password, size_t password_len,
600 struct sae_data *sae)
603 return sae_prepare_commit_ec(addr1, addr2, password,
608 return sae_prepare_commit_dh(addr1, addr2, password,
616 static int sae_check_peer_commit(struct sae_data *sae)
618 u8 order[SAE_MAX_PRIME_LEN], prime[SAE_MAX_PRIME_LEN];
620 if (crypto_bignum_to_bin(sae->order, order, sizeof(order),
621 sae->prime_len) < 0 ||
622 crypto_bignum_to_bin(sae->prime, prime, sizeof(prime),
627 if (val_zero(sae->peer_commit_scalar, sae->prime_len) ||
628 os_memcmp(sae->peer_commit_scalar, order, sae->prime_len) >= 0) {
629 wpa_printf(MSG_DEBUG, "SAE: Invalid peer scalar");
634 if (os_memcmp(sae->peer_commit_element, prime, sae->prime_len)
636 val_zero_or_one(sae->peer_commit_element, sae->prime_len)) {
637 wpa_printf(MSG_DEBUG, "SAE: Invalid peer element");
643 /* element x and y coordinates < p */
644 if (os_memcmp(sae->peer_commit_element, prime, sae->prime_len) >= 0 ||
645 os_memcmp(sae->peer_commit_element + sae->prime_len, prime,
646 sae->prime_len) >= 0) {
647 wpa_printf(MSG_DEBUG, "SAE: Invalid coordinates in peer "
656 static int sae_derive_k_ec(struct sae_data *sae, u8 *k)
658 struct crypto_ec_point *pwe, *peer_elem, *K;
659 struct crypto_bignum *rand_bn, *peer_scalar;
662 pwe = crypto_ec_point_from_bin(sae->ec, sae->pwe);
663 peer_scalar = crypto_bignum_init_set(sae->peer_commit_scalar,
665 peer_elem = crypto_ec_point_from_bin(sae->ec, sae->peer_commit_element);
666 K = crypto_ec_point_init(sae->ec);
667 rand_bn = crypto_bignum_init_set(sae->sae_rand, sae->prime_len);
668 if (pwe == NULL || peer_elem == NULL || peer_scalar == NULL ||
669 K == NULL || rand_bn == NULL)
672 if (!crypto_ec_point_is_on_curve(sae->ec, peer_elem)) {
673 wpa_printf(MSG_DEBUG, "SAE: Peer element is not on curve");
678 * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE),
679 * PEER-COMMIT-ELEMENT)))
680 * If K is identity element (point-at-infinity), reject
681 * k = F(K) (= x coordinate)
684 if (crypto_ec_point_mul(sae->ec, pwe, peer_scalar, K) < 0 ||
685 crypto_ec_point_add(sae->ec, K, peer_elem, K) < 0 ||
686 crypto_ec_point_mul(sae->ec, K, rand_bn, K) < 0 ||
687 crypto_ec_point_is_at_infinity(sae->ec, K) ||
688 crypto_ec_point_to_bin(sae->ec, K, k, NULL) < 0) {
689 wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k");
693 wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->prime_len);
697 crypto_ec_point_deinit(pwe, 1);
698 crypto_ec_point_deinit(peer_elem, 0);
699 crypto_ec_point_deinit(K, 1);
700 crypto_bignum_deinit(rand_bn, 1);
705 static int sae_derive_k_dh(struct sae_data *sae, u8 *k)
707 struct crypto_bignum *pwe, *peer_elem, *K, *rand_bn, *peer_scalar;
710 pwe = crypto_bignum_init_set(sae->pwe, sae->prime_len);
711 peer_scalar = crypto_bignum_init_set(sae->peer_commit_scalar,
713 peer_elem = crypto_bignum_init_set(sae->peer_commit_element,
715 K = crypto_bignum_init();
716 rand_bn = crypto_bignum_init_set(sae->sae_rand, sae->prime_len);
717 if (pwe == NULL || peer_elem == NULL || peer_scalar == NULL ||
718 K == NULL || rand_bn == NULL)
722 * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE),
723 * PEER-COMMIT-ELEMENT)))
724 * If K is identity element (one), reject.
725 * k = F(K) (= x coordinate)
728 if (crypto_bignum_exptmod(pwe, peer_scalar, sae->prime, K) < 0 ||
729 crypto_bignum_mulmod(K, peer_elem, sae->prime, K) < 0 ||
730 crypto_bignum_exptmod(K, rand_bn, sae->prime, K) < 0 ||
731 crypto_bignum_to_bin(K, k, SAE_MAX_PRIME_LEN, sae->prime_len) < 0 ||
732 val_one(k, sae->prime_len)) {
733 wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k");
737 wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->prime_len);
741 crypto_bignum_deinit(pwe, 1);
742 crypto_bignum_deinit(peer_elem, 0);
743 crypto_bignum_deinit(K, 1);
744 crypto_bignum_deinit(rand_bn, 1);
749 static int sae_derive_k(struct sae_data *sae, u8 *k)
752 return sae_derive_k_ec(sae, k);
753 return sae_derive_k_dh(sae, k);
757 static int sae_derive_keys(struct sae_data *sae, const u8 *k)
759 u8 null_key[SAE_KEYSEED_KEY_LEN], val[SAE_MAX_PRIME_LEN];
760 u8 keyseed[SHA256_MAC_LEN];
761 u8 keys[SAE_KCK_LEN + SAE_PMK_LEN];
762 struct crypto_bignum *own_scalar, *peer_scalar, *tmp;
765 own_scalar = crypto_bignum_init_set(sae->own_commit_scalar,
767 peer_scalar = crypto_bignum_init_set(sae->peer_commit_scalar,
769 tmp = crypto_bignum_init();
770 if (own_scalar == NULL || peer_scalar == NULL || tmp == NULL)
773 /* keyseed = H(<0>32, k)
774 * KCK || PMK = KDF-512(keyseed, "SAE KCK and PMK",
775 * (commit-scalar + peer-commit-scalar) modulo r)
776 * PMKID = L((commit-scalar + peer-commit-scalar) modulo r, 0, 128)
779 os_memset(null_key, 0, sizeof(null_key));
780 hmac_sha256(null_key, sizeof(null_key), k, sae->prime_len, keyseed);
781 wpa_hexdump_key(MSG_DEBUG, "SAE: keyseed", keyseed, sizeof(keyseed));
783 crypto_bignum_add(own_scalar, peer_scalar, tmp);
784 crypto_bignum_mod(tmp, sae->order, tmp);
785 crypto_bignum_to_bin(tmp, val, sizeof(val), sae->prime_len);
786 wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN);
787 sha256_prf(keyseed, sizeof(keyseed), "SAE KCK and PMK",
788 val, sae->prime_len, keys, sizeof(keys));
789 os_memcpy(sae->kck, keys, SAE_KCK_LEN);
790 os_memcpy(sae->pmk, keys + SAE_KCK_LEN, SAE_PMK_LEN);
791 wpa_hexdump_key(MSG_DEBUG, "SAE: KCK", sae->kck, SAE_KCK_LEN);
792 wpa_hexdump_key(MSG_DEBUG, "SAE: PMK", sae->pmk, SAE_PMK_LEN);
796 crypto_bignum_deinit(tmp, 0);
797 crypto_bignum_deinit(peer_scalar, 0);
798 crypto_bignum_deinit(own_scalar, 0);
803 int sae_process_commit(struct sae_data *sae)
805 u8 k[SAE_MAX_PRIME_LEN];
806 if (sae_check_peer_commit(sae) < 0 ||
807 sae_derive_k(sae, k) < 0 ||
808 sae_derive_keys(sae, k) < 0)
814 void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
815 const struct wpabuf *token)
817 wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */
819 wpabuf_put_buf(buf, token);
820 wpabuf_put_data(buf, sae->own_commit_scalar, sae->prime_len);
821 wpabuf_put_data(buf, sae->own_commit_element,
822 (sae->ec ? 2 : 1) * sae->prime_len);
826 u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
827 const u8 **token, size_t *token_len, int *allowed_groups)
829 const u8 *pos = data, *end = data + len;
832 wpa_hexdump(MSG_DEBUG, "SAE: Commit fields", data, len);
838 /* Check Finite Cyclic Group */
840 return WLAN_STATUS_UNSPECIFIED_FAILURE;
841 group = WPA_GET_LE16(pos);
842 if (allowed_groups) {
844 for (i = 0; allowed_groups[i] >= 0; i++) {
845 if (allowed_groups[i] == group)
848 if (allowed_groups[i] != group) {
849 wpa_printf(MSG_DEBUG, "SAE: Proposed group %u not "
850 "enabled in the current configuration",
852 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
855 if (sae->state == SAE_COMMITTED && group != sae->group) {
856 wpa_printf(MSG_DEBUG, "SAE: Do not allow group to be changed");
857 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
859 if (group != sae->group && sae_set_group(sae, group) < 0) {
860 wpa_printf(MSG_DEBUG, "SAE: Unsupported Finite Cyclic Group %u",
862 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
864 if (sae->dh && !allowed_groups) {
865 wpa_printf(MSG_DEBUG, "SAE: Do not allow FFC group %u without "
866 "explicit configuration enabling it", group);
867 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
871 if (pos + (sae->ec ? 3 : 2) * sae->prime_len < end) {
872 size_t tlen = end - (pos + (sae->ec ? 3 : 2) * sae->prime_len);
873 wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token", pos, tlen);
881 if (pos + sae->prime_len > end) {
882 wpa_printf(MSG_DEBUG, "SAE: Not enough data for scalar");
883 return WLAN_STATUS_UNSPECIFIED_FAILURE;
887 * IEEE Std 802.11-2012, 11.3.8.6.1: If there is a protocol instance for
888 * the peer and it is in Authenticated state, the new Commit Message
889 * shall be dropped if the peer-scalar is identical to the one used in
890 * the existing protocol instance.
892 if (sae->state == SAE_ACCEPTED &&
893 os_memcmp(sae->peer_commit_scalar, pos, sae->prime_len) == 0) {
894 wpa_printf(MSG_DEBUG, "SAE: Do not accept re-use of previous "
895 "peer-commit-scalar");
896 return WLAN_STATUS_UNSPECIFIED_FAILURE;
899 os_memcpy(sae->peer_commit_scalar, pos, sae->prime_len);
900 wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-scalar",
901 sae->peer_commit_scalar, sae->prime_len);
902 pos += sae->prime_len;
905 if (pos + sae->prime_len > end) {
906 wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
908 return WLAN_STATUS_UNSPECIFIED_FAILURE;
910 os_memcpy(sae->peer_commit_element, pos, sae->prime_len);
911 wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element",
912 sae->peer_commit_element, sae->prime_len);
914 return WLAN_STATUS_SUCCESS;
917 if (pos + 2 * sae->prime_len > end) {
918 wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
920 return WLAN_STATUS_UNSPECIFIED_FAILURE;
922 os_memcpy(sae->peer_commit_element, pos, 2 * sae->prime_len);
923 wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(x)",
924 sae->peer_commit_element, sae->prime_len);
925 wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(y)",
926 sae->peer_commit_element + sae->prime_len, sae->prime_len);
928 return WLAN_STATUS_SUCCESS;
932 void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
939 sc = wpabuf_put(buf, 0);
940 wpabuf_put_le16(buf, sae->send_confirm);
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)
951 addr[1] = sae->own_commit_scalar;
952 len[1] = sae->prime_len;
953 addr[2] = sae->own_commit_element;
954 len[2] = (sae->ec ? 2 : 1) * sae->prime_len;
955 addr[3] = sae->peer_commit_scalar;
956 len[3] = sae->prime_len;
957 addr[4] = sae->peer_commit_element;
958 len[4] = (sae->ec ? 2 : 1) * sae->prime_len;
959 hmac_sha256_vector(sae->kck, sizeof(sae->kck), 5, addr, len,
960 wpabuf_put(buf, SHA256_MAC_LEN));
964 int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
969 u8 verifier[SHA256_MAC_LEN];
971 wpa_hexdump(MSG_DEBUG, "SAE: Confirm fields", data, len);
973 if (len < 2 + SHA256_MAC_LEN) {
974 wpa_printf(MSG_DEBUG, "SAE: Too short confirm message");
978 rc = WPA_GET_LE16(data);
979 wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", rc);
982 * CN(key, X, Y, Z, ...) =
983 * HMAC-SHA256(key, D2OS(X) || D2OS(Y) || D2OS(Z) | ...)
984 * verifier = CN(KCK, peer-send-confirm, peer-commit-scalar,
985 * PEER-COMMIT-ELEMENT, commit-scalar, COMMIT-ELEMENT)
989 addr[1] = sae->peer_commit_scalar;
990 elen[1] = sae->prime_len;
991 addr[2] = sae->peer_commit_element;
992 elen[2] = (sae->ec ? 2 : 1) * sae->prime_len;
993 addr[3] = sae->own_commit_scalar;
994 elen[3] = sae->prime_len;
995 addr[4] = sae->own_commit_element;
996 elen[4] = (sae->ec ? 2 : 1) * sae->prime_len;
997 hmac_sha256_vector(sae->kck, sizeof(sae->kck), 5, addr, elen, verifier);
999 if (os_memcmp(verifier, data + 2, SHA256_MAC_LEN) != 0) {
1000 wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch");
1001 wpa_hexdump(MSG_DEBUG, "SAE: Received confirm",
1002 data + 2, SHA256_MAC_LEN);
1003 wpa_hexdump(MSG_DEBUG, "SAE: Calculated verifier",
1004 verifier, SHA256_MAC_LEN);