sae.c 28 KB

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