sae.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. /*
  2. * Simultaneous authentication of equals
  3. * Copyright (c) 2012, 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. #include "includes.h"
  9. #include "common.h"
  10. #include "crypto/crypto.h"
  11. #include "crypto/sha256.h"
  12. #include "crypto/random.h"
  13. #include "ieee802_11_defs.h"
  14. #include "sae.h"
  15. static const u8 group19_prime[] = {
  16. 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
  17. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  18. 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
  19. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
  20. };
  21. static const u8 group19_order[] = {
  22. 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
  23. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  24. 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
  25. 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51
  26. };
  27. int sae_set_group(struct sae_data *sae, int group)
  28. {
  29. crypto_ec_deinit(sae->ec);
  30. sae->ec = crypto_ec_init(group);
  31. if (!sae->ec)
  32. return -1;
  33. sae->group = group;
  34. sae->prime_len = crypto_ec_prime_len(sae->ec);
  35. return 0;
  36. }
  37. void sae_clear_data(struct sae_data *sae)
  38. {
  39. if (sae == NULL)
  40. return;
  41. crypto_ec_deinit(sae->ec);
  42. os_memset(sae, 0, sizeof(*sae));
  43. }
  44. static int val_zero_or_one(const u8 *val, size_t len)
  45. {
  46. size_t i;
  47. for (i = 0; i < len - 1; i++) {
  48. if (val[i])
  49. return 0;
  50. }
  51. return val[len - 1] <= 1;
  52. }
  53. static int val_zero(const u8 *val, size_t len)
  54. {
  55. size_t i;
  56. for (i = 0; i < len; i++) {
  57. if (val[i])
  58. return 0;
  59. }
  60. return 1;
  61. }
  62. static int sae_get_rand(u8 *val)
  63. {
  64. int iter = 0;
  65. do {
  66. if (random_get_bytes(val, sizeof(group19_prime)) < 0)
  67. return -1;
  68. if (iter++ > 100)
  69. return -1;
  70. } while (os_memcmp(val, group19_order, sizeof(group19_prime)) >= 0 ||
  71. val_zero_or_one(val, sizeof(group19_prime)));
  72. return 0;
  73. }
  74. static void sae_pwd_seed_key(const u8 *addr1, const u8 *addr2, u8 *key)
  75. {
  76. wpa_printf(MSG_DEBUG, "SAE: PWE derivation - addr1=" MACSTR
  77. " addr2=" MACSTR, MAC2STR(addr1), MAC2STR(addr2));
  78. if (os_memcmp(addr1, addr2, ETH_ALEN) > 0) {
  79. os_memcpy(key, addr1, ETH_ALEN);
  80. os_memcpy(key + ETH_ALEN, addr2, ETH_ALEN);
  81. } else {
  82. os_memcpy(key, addr2, ETH_ALEN);
  83. os_memcpy(key + ETH_ALEN, addr1, ETH_ALEN);
  84. }
  85. }
  86. static int sae_test_pwd_seed(struct sae_data *sae, const u8 *pwd_seed,
  87. struct crypto_ec_point *pwe, u8 *pwe_bin)
  88. {
  89. u8 pwd_value[SAE_MAX_PRIME_LEN];
  90. struct crypto_bignum *x;
  91. int y_bit;
  92. wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
  93. /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */
  94. sha256_prf(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking",
  95. group19_prime, sizeof(group19_prime),
  96. pwd_value, sizeof(pwd_value));
  97. wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value",
  98. pwd_value, sizeof(pwd_value));
  99. if (os_memcmp(pwd_value, group19_prime, sizeof(group19_prime)) >= 0)
  100. return 0;
  101. y_bit = pwd_seed[SHA256_MAC_LEN - 1] & 0x01;
  102. x = crypto_bignum_init_set(pwd_value, sizeof(pwd_value));
  103. if (x == NULL)
  104. return -1;
  105. if (crypto_ec_point_solve_y_coord(sae->ec, pwe, x, y_bit) < 0) {
  106. crypto_bignum_deinit(x, 0);
  107. wpa_printf(MSG_DEBUG, "SAE: No solution found");
  108. return 0;
  109. }
  110. crypto_bignum_deinit(x, 0);
  111. wpa_printf(MSG_DEBUG, "SAE: PWE found");
  112. if (crypto_ec_point_to_bin(sae->ec, pwe, pwe_bin,
  113. pwe_bin + sae->prime_len) < 0)
  114. return -1;
  115. wpa_hexdump_key(MSG_DEBUG, "SAE: PWE x", pwe_bin, sae->prime_len);
  116. wpa_hexdump_key(MSG_DEBUG, "SAE: PWE y",
  117. pwe_bin + sae->prime_len, sae->prime_len);
  118. return 1;
  119. }
  120. static int sae_derive_pwe(struct sae_data *sae, const u8 *addr1,
  121. const u8 *addr2, const u8 *password,
  122. size_t password_len, struct crypto_ec_point *pwe,
  123. u8 *pwe_bin)
  124. {
  125. u8 counter, k = 4;
  126. u8 addrs[2 * ETH_ALEN];
  127. const u8 *addr[2];
  128. size_t len[2];
  129. int found = 0;
  130. struct crypto_ec_point *pwe_tmp;
  131. u8 pwe_bin_tmp[2 * SAE_MAX_PRIME_LEN];
  132. pwe_tmp = crypto_ec_point_init(sae->ec);
  133. if (pwe_tmp == NULL)
  134. return -1;
  135. wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
  136. password, password_len);
  137. /*
  138. * H(salt, ikm) = HMAC-SHA256(salt, ikm)
  139. * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
  140. * password || counter)
  141. */
  142. sae_pwd_seed_key(addr1, addr2, addrs);
  143. addr[0] = password;
  144. len[0] = password_len;
  145. addr[1] = &counter;
  146. len[1] = sizeof(counter);
  147. /*
  148. * Continue for at least k iterations to protect against side-channel
  149. * attacks that attempt to determine the number of iterations required
  150. * in the loop.
  151. */
  152. for (counter = 1; counter < k || !found; counter++) {
  153. u8 pwd_seed[SHA256_MAC_LEN];
  154. int res;
  155. wpa_printf(MSG_DEBUG, "SAE: counter = %u", counter);
  156. if (hmac_sha256_vector(addrs, sizeof(addrs), 2, addr, len,
  157. pwd_seed) < 0)
  158. break;
  159. res = sae_test_pwd_seed(sae, pwd_seed,
  160. found ? pwe_tmp : pwe,
  161. found ? pwe_bin_tmp : pwe_bin);
  162. if (res < 0)
  163. break;
  164. if (res == 0)
  165. continue;
  166. if (found) {
  167. wpa_printf(MSG_DEBUG, "SAE: Ignore this PWE (one was "
  168. "already selected)");
  169. } else {
  170. wpa_printf(MSG_DEBUG, "SAE: Use this PWE");
  171. found = 1;
  172. }
  173. if (counter > 200) {
  174. /* This should not happen in practice */
  175. wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE");
  176. break;
  177. }
  178. }
  179. crypto_ec_point_deinit(pwe_tmp, 1);
  180. return found ? 0 : -1;
  181. }
  182. static int sae_derive_commit(struct sae_data *sae, struct crypto_ec_point *pwe)
  183. {
  184. struct crypto_bignum *x, *bn_rand, *bn_mask;
  185. struct crypto_ec_point *elem;
  186. u8 mask[SAE_MAX_PRIME_LEN];
  187. int ret = -1;
  188. if (sae_get_rand(sae->sae_rand) < 0 || sae_get_rand(mask) < 0)
  189. return -1;
  190. wpa_hexdump_key(MSG_DEBUG, "SAE: rand",
  191. sae->sae_rand, sizeof(sae->sae_rand));
  192. wpa_hexdump_key(MSG_DEBUG, "SAE: mask", mask, sizeof(mask));
  193. x = crypto_bignum_init();
  194. bn_rand = crypto_bignum_init_set(sae->sae_rand, sae->prime_len);
  195. bn_mask = crypto_bignum_init_set(mask, sizeof(mask));
  196. elem = crypto_ec_point_init(sae->ec);
  197. if (x == NULL || bn_rand == NULL || bn_mask == NULL || elem == NULL)
  198. goto fail;
  199. /* commit-scalar = (rand + mask) modulo r */
  200. crypto_bignum_add(bn_rand, bn_mask, x);
  201. crypto_bignum_mod(x, crypto_ec_get_order(sae->ec), x);
  202. crypto_bignum_to_bin(x, sae->own_commit_scalar,
  203. sizeof(sae->own_commit_scalar), sae->prime_len);
  204. wpa_hexdump(MSG_DEBUG, "SAE: commit-scalar",
  205. sae->own_commit_scalar, sae->prime_len);
  206. /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */
  207. if (crypto_ec_point_mul(sae->ec, pwe, bn_mask, elem) < 0 ||
  208. crypto_ec_point_invert(sae->ec, elem) < 0 ||
  209. crypto_ec_point_to_bin(sae->ec, elem, sae->own_commit_element,
  210. sae->own_commit_element + sae->prime_len) <
  211. 0)
  212. goto fail;
  213. wpa_hexdump(MSG_DEBUG, "SAE: commit-element x",
  214. sae->own_commit_element, sae->prime_len);
  215. wpa_hexdump(MSG_DEBUG, "SAE: commit-element y",
  216. sae->own_commit_element + sae->prime_len, sae->prime_len);
  217. ret = 0;
  218. fail:
  219. crypto_ec_point_deinit(elem, 0);
  220. crypto_bignum_deinit(bn_mask, 1);
  221. os_memset(mask, 0, sizeof(mask));
  222. crypto_bignum_deinit(bn_rand, 1);
  223. crypto_bignum_deinit(x, 1);
  224. return ret;
  225. }
  226. int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
  227. const u8 *password, size_t password_len,
  228. struct sae_data *sae)
  229. {
  230. struct crypto_ec_point *pwe;
  231. int ret = 0;
  232. pwe = crypto_ec_point_init(sae->ec);
  233. if (pwe == NULL ||
  234. sae_derive_pwe(sae, addr1, addr2, password, password_len, pwe,
  235. sae->pwe) < 0 ||
  236. sae_derive_commit(sae, pwe) < 0)
  237. ret = -1;
  238. crypto_ec_point_deinit(pwe, 1);
  239. return ret;
  240. }
  241. static int sae_check_peer_commit(struct sae_data *sae)
  242. {
  243. /* 0 < scalar < r */
  244. if (val_zero(sae->peer_commit_scalar, sae->prime_len) ||
  245. os_memcmp(sae->peer_commit_scalar, group19_order,
  246. sizeof(group19_prime)) >= 0) {
  247. wpa_printf(MSG_DEBUG, "SAE: Invalid peer scalar");
  248. return -1;
  249. }
  250. /* element x and y coordinates < p */
  251. if (os_memcmp(sae->peer_commit_element, group19_prime,
  252. sizeof(group19_prime)) >= 0 ||
  253. os_memcmp(sae->peer_commit_element + sae->prime_len, group19_prime,
  254. sizeof(group19_prime)) >= 0) {
  255. wpa_printf(MSG_DEBUG, "SAE: Invalid coordinates in peer "
  256. "element");
  257. return -1;
  258. }
  259. return 0;
  260. }
  261. static int sae_derive_k(struct sae_data *sae, u8 *k)
  262. {
  263. struct crypto_ec_point *pwe, *peer_elem, *K;
  264. struct crypto_bignum *rand_bn, *peer_scalar;
  265. int ret = -1;
  266. pwe = crypto_ec_point_from_bin(sae->ec, sae->pwe);
  267. peer_scalar = crypto_bignum_init_set(sae->peer_commit_scalar,
  268. sae->prime_len);
  269. peer_elem = crypto_ec_point_from_bin(sae->ec, sae->peer_commit_element);
  270. K = crypto_ec_point_init(sae->ec);
  271. rand_bn = crypto_bignum_init_set(sae->sae_rand, sae->prime_len);
  272. if (pwe == NULL || peer_elem == NULL || peer_scalar == NULL ||
  273. K == NULL || rand_bn == NULL)
  274. goto fail;
  275. if (!crypto_ec_point_is_on_curve(sae->ec, peer_elem)) {
  276. wpa_printf(MSG_DEBUG, "SAE: Peer element is not on curve");
  277. goto fail;
  278. }
  279. /*
  280. * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE),
  281. * PEER-COMMIT-ELEMENT)))
  282. * If K is identity element (point-at-infinity), reject
  283. * k = F(K) (= x coordinate)
  284. */
  285. if (crypto_ec_point_mul(sae->ec, pwe, peer_scalar, K) < 0 ||
  286. crypto_ec_point_add(sae->ec, K, peer_elem, K) < 0 ||
  287. crypto_ec_point_mul(sae->ec, K, rand_bn, K) < 0 ||
  288. crypto_ec_point_is_at_infinity(sae->ec, K) ||
  289. crypto_ec_point_to_bin(sae->ec, K, k, NULL) < 0) {
  290. wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k");
  291. goto fail;
  292. }
  293. wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->prime_len);
  294. ret = 0;
  295. fail:
  296. crypto_ec_point_deinit(pwe, 1);
  297. crypto_ec_point_deinit(peer_elem, 0);
  298. crypto_ec_point_deinit(K, 1);
  299. crypto_bignum_deinit(rand_bn, 1);
  300. return ret;
  301. }
  302. static int sae_derive_keys(struct sae_data *sae, const u8 *k)
  303. {
  304. u8 null_key[SAE_KEYSEED_KEY_LEN], val[SAE_MAX_PRIME_LEN];
  305. u8 keyseed[SHA256_MAC_LEN];
  306. u8 keys[SAE_KCK_LEN + SAE_PMK_LEN];
  307. struct crypto_bignum *own_scalar, *peer_scalar, *tmp;
  308. int ret = -1;
  309. own_scalar = crypto_bignum_init_set(sae->own_commit_scalar,
  310. sae->prime_len);
  311. peer_scalar = crypto_bignum_init_set(sae->peer_commit_scalar,
  312. sae->prime_len);
  313. tmp = crypto_bignum_init();
  314. if (own_scalar == NULL || peer_scalar == NULL || tmp == NULL)
  315. goto fail;
  316. /* keyseed = H(<0>32, k)
  317. * KCK || PMK = KDF-512(keyseed, "SAE KCK and PMK",
  318. * (commit-scalar + peer-commit-scalar) modulo r)
  319. * PMKID = L((commit-scalar + peer-commit-scalar) modulo r, 0, 128)
  320. */
  321. os_memset(null_key, 0, sizeof(null_key));
  322. hmac_sha256(null_key, sizeof(null_key), k, sae->prime_len, keyseed);
  323. wpa_hexdump_key(MSG_DEBUG, "SAE: keyseed", keyseed, sizeof(keyseed));
  324. crypto_bignum_add(own_scalar, peer_scalar, tmp);
  325. crypto_bignum_mod(tmp, crypto_ec_get_order(sae->ec), tmp);
  326. crypto_bignum_to_bin(tmp, val, sizeof(val), sae->prime_len);
  327. wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN);
  328. sha256_prf(keyseed, sizeof(keyseed), "SAE KCK and PMK",
  329. val, sae->prime_len, keys, sizeof(keys));
  330. os_memcpy(sae->kck, keys, SAE_KCK_LEN);
  331. os_memcpy(sae->pmk, keys + SAE_KCK_LEN, SAE_PMK_LEN);
  332. wpa_hexdump_key(MSG_DEBUG, "SAE: KCK", sae->kck, SAE_KCK_LEN);
  333. wpa_hexdump_key(MSG_DEBUG, "SAE: PMK", sae->pmk, SAE_PMK_LEN);
  334. ret = 0;
  335. fail:
  336. crypto_bignum_deinit(tmp, 0);
  337. crypto_bignum_deinit(peer_scalar, 0);
  338. crypto_bignum_deinit(own_scalar, 0);
  339. return ret;
  340. }
  341. int sae_process_commit(struct sae_data *sae)
  342. {
  343. u8 k[SAE_MAX_PRIME_LEN];
  344. if (sae_check_peer_commit(sae) < 0 ||
  345. sae_derive_k(sae, k) < 0 ||
  346. sae_derive_keys(sae, k) < 0)
  347. return -1;
  348. return 0;
  349. }
  350. void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
  351. const struct wpabuf *token)
  352. {
  353. wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */
  354. if (token)
  355. wpabuf_put_buf(buf, token);
  356. wpabuf_put_data(buf, sae->own_commit_scalar, sae->prime_len);
  357. wpabuf_put_data(buf, sae->own_commit_element, 2 * sae->prime_len);
  358. }
  359. u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
  360. const u8 **token, size_t *token_len)
  361. {
  362. const u8 *pos = data, *end = data + len;
  363. u16 group;
  364. wpa_hexdump(MSG_DEBUG, "SAE: Commit fields", data, len);
  365. if (token)
  366. *token = NULL;
  367. if (token_len)
  368. *token_len = 0;
  369. /* Check Finite Cyclic Group */
  370. if (pos + 2 > end)
  371. return WLAN_STATUS_UNSPECIFIED_FAILURE;
  372. group = WPA_GET_LE16(pos);
  373. if (sae->state == SAE_COMMITTED && group != sae->group) {
  374. wpa_printf(MSG_DEBUG, "SAE: Do not allow group to be changed");
  375. return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
  376. }
  377. if (group != sae->group && sae_set_group(sae, group) < 0) {
  378. wpa_printf(MSG_DEBUG, "SAE: Unsupported Finite Cyclic Group %u",
  379. group);
  380. return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
  381. }
  382. pos += 2;
  383. if (pos + 3 * sae->prime_len < end) {
  384. size_t tlen = end - (pos + 3 * sae->prime_len);
  385. wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token", pos, tlen);
  386. if (token)
  387. *token = pos;
  388. if (token_len)
  389. *token_len = tlen;
  390. pos += tlen;
  391. }
  392. if (pos + sae->prime_len > end) {
  393. wpa_printf(MSG_DEBUG, "SAE: Not enough data for scalar");
  394. return WLAN_STATUS_UNSPECIFIED_FAILURE;
  395. }
  396. /*
  397. * IEEE Std 802.11-2012, 11.3.8.6.1: If there is a protocol instance for
  398. * the peer and it is in Authenticated state, the new Commit Message
  399. * shall be dropped if the peer-scalar is identical to the one used in
  400. * the existing protocol instance.
  401. */
  402. if (sae->state == SAE_ACCEPTED &&
  403. os_memcmp(sae->peer_commit_scalar, pos, sae->prime_len) == 0) {
  404. wpa_printf(MSG_DEBUG, "SAE: Do not accept re-use of previous "
  405. "peer-commit-scalar");
  406. return WLAN_STATUS_UNSPECIFIED_FAILURE;
  407. }
  408. os_memcpy(sae->peer_commit_scalar, pos, sae->prime_len);
  409. wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-scalar",
  410. sae->peer_commit_scalar, sae->prime_len);
  411. pos += sae->prime_len;
  412. if (pos + 2 * sae->prime_len > end) {
  413. wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
  414. "commit-element");
  415. return WLAN_STATUS_UNSPECIFIED_FAILURE;
  416. }
  417. os_memcpy(sae->peer_commit_element, pos, 2 * sae->prime_len);
  418. wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(x)",
  419. sae->peer_commit_element, sae->prime_len);
  420. wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(y)",
  421. sae->peer_commit_element + sae->prime_len, sae->prime_len);
  422. return WLAN_STATUS_SUCCESS;
  423. }
  424. void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
  425. {
  426. const u8 *sc;
  427. const u8 *addr[5];
  428. size_t len[5];
  429. /* Send-Confirm */
  430. sc = wpabuf_put(buf, 0);
  431. wpabuf_put_le16(buf, sae->send_confirm);
  432. sae->send_confirm++;
  433. /* Confirm
  434. * CN(key, X, Y, Z, ...) =
  435. * HMAC-SHA256(key, D2OS(X) || D2OS(Y) || D2OS(Z) | ...)
  436. * confirm = CN(KCK, send-confirm, commit-scalar, COMMIT-ELEMENT,
  437. * peer-commit-scalar, PEER-COMMIT-ELEMENT)
  438. */
  439. addr[0] = sc;
  440. len[0] = 2;
  441. addr[1] = sae->own_commit_scalar;
  442. len[1] = sae->prime_len;
  443. addr[2] = sae->own_commit_element;
  444. len[2] = 2 * sae->prime_len;
  445. addr[3] = sae->peer_commit_scalar;
  446. len[3] = sae->prime_len;
  447. addr[4] = sae->peer_commit_element;
  448. len[4] = 2 * sae->prime_len;
  449. hmac_sha256_vector(sae->kck, sizeof(sae->kck), 5, addr, len,
  450. wpabuf_put(buf, SHA256_MAC_LEN));
  451. }
  452. int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
  453. {
  454. u16 rc;
  455. const u8 *addr[5];
  456. size_t elen[5];
  457. u8 verifier[SHA256_MAC_LEN];
  458. wpa_hexdump(MSG_DEBUG, "SAE: Confirm fields", data, len);
  459. if (len < 2 + SHA256_MAC_LEN) {
  460. wpa_printf(MSG_DEBUG, "SAE: Too short confirm message");
  461. return -1;
  462. }
  463. rc = WPA_GET_LE16(data);
  464. wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", rc);
  465. /* Confirm
  466. * CN(key, X, Y, Z, ...) =
  467. * HMAC-SHA256(key, D2OS(X) || D2OS(Y) || D2OS(Z) | ...)
  468. * verifier = CN(KCK, peer-send-confirm, peer-commit-scalar,
  469. * PEER-COMMIT-ELEMENT, commit-scalar, COMMIT-ELEMENT)
  470. */
  471. addr[0] = data;
  472. elen[0] = 2;
  473. addr[1] = sae->peer_commit_scalar;
  474. elen[1] = sae->prime_len;
  475. addr[2] = sae->peer_commit_element;
  476. elen[2] = 2 * sae->prime_len;
  477. addr[3] = sae->own_commit_scalar;
  478. elen[3] = sae->prime_len;
  479. addr[4] = sae->own_commit_element;
  480. elen[4] = 2 * sae->prime_len;
  481. hmac_sha256_vector(sae->kck, sizeof(sae->kck), 5, addr, elen, verifier);
  482. if (os_memcmp(verifier, data + 2, SHA256_MAC_LEN) != 0) {
  483. wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch");
  484. wpa_hexdump(MSG_DEBUG, "SAE: Received confirm",
  485. data + 2, SHA256_MAC_LEN);
  486. wpa_hexdump(MSG_DEBUG, "SAE: Calculated verifier",
  487. verifier, SHA256_MAC_LEN);
  488. return -1;
  489. }
  490. return 0;
  491. }