sae.c 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028
  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->dh && !allowed_groups) {
  589. wpa_printf(MSG_DEBUG, "SAE: Do not allow FFC group %u without "
  590. "explicit configuration enabling it", group);
  591. return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
  592. }
  593. return WLAN_STATUS_SUCCESS;
  594. }
  595. static void sae_parse_commit_token(struct sae_data *sae, const u8 **pos,
  596. const u8 *end, const u8 **token,
  597. size_t *token_len)
  598. {
  599. if (*pos + (sae->tmp->ec ? 3 : 2) * sae->tmp->prime_len < end) {
  600. size_t tlen = end - (*pos + (sae->tmp->ec ? 3 : 2) *
  601. sae->tmp->prime_len);
  602. wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token", *pos, tlen);
  603. if (token)
  604. *token = *pos;
  605. if (token_len)
  606. *token_len = tlen;
  607. *pos += tlen;
  608. } else {
  609. if (token)
  610. *token = NULL;
  611. if (token_len)
  612. *token_len = 0;
  613. }
  614. }
  615. static u16 sae_parse_commit_scalar(struct sae_data *sae, const u8 **pos,
  616. const u8 *end)
  617. {
  618. struct crypto_bignum *peer_scalar;
  619. if (*pos + sae->tmp->prime_len > end) {
  620. wpa_printf(MSG_DEBUG, "SAE: Not enough data for scalar");
  621. return WLAN_STATUS_UNSPECIFIED_FAILURE;
  622. }
  623. peer_scalar = crypto_bignum_init_set(*pos, sae->tmp->prime_len);
  624. if (peer_scalar == NULL)
  625. return WLAN_STATUS_UNSPECIFIED_FAILURE;
  626. /*
  627. * IEEE Std 802.11-2012, 11.3.8.6.1: If there is a protocol instance for
  628. * the peer and it is in Authenticated state, the new Commit Message
  629. * shall be dropped if the peer-scalar is identical to the one used in
  630. * the existing protocol instance.
  631. */
  632. if (sae->state == SAE_ACCEPTED && sae->peer_commit_scalar &&
  633. crypto_bignum_cmp(sae->peer_commit_scalar, peer_scalar) == 0) {
  634. wpa_printf(MSG_DEBUG, "SAE: Do not accept re-use of previous "
  635. "peer-commit-scalar");
  636. crypto_bignum_deinit(peer_scalar, 0);
  637. return WLAN_STATUS_UNSPECIFIED_FAILURE;
  638. }
  639. /* 0 < scalar < r */
  640. if (crypto_bignum_is_zero(peer_scalar) ||
  641. crypto_bignum_cmp(peer_scalar, sae->tmp->order) >= 0) {
  642. wpa_printf(MSG_DEBUG, "SAE: Invalid peer scalar");
  643. crypto_bignum_deinit(peer_scalar, 0);
  644. return WLAN_STATUS_UNSPECIFIED_FAILURE;
  645. }
  646. crypto_bignum_deinit(sae->peer_commit_scalar, 0);
  647. sae->peer_commit_scalar = peer_scalar;
  648. wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-scalar",
  649. *pos, sae->tmp->prime_len);
  650. *pos += sae->tmp->prime_len;
  651. return WLAN_STATUS_SUCCESS;
  652. }
  653. static u16 sae_parse_commit_element_ecc(struct sae_data *sae, const u8 *pos,
  654. const u8 *end)
  655. {
  656. u8 prime[SAE_MAX_ECC_PRIME_LEN];
  657. if (pos + 2 * sae->tmp->prime_len > end) {
  658. wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
  659. "commit-element");
  660. return WLAN_STATUS_UNSPECIFIED_FAILURE;
  661. }
  662. if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime),
  663. sae->tmp->prime_len) < 0)
  664. return WLAN_STATUS_UNSPECIFIED_FAILURE;
  665. /* element x and y coordinates < p */
  666. if (os_memcmp(pos, prime, sae->tmp->prime_len) >= 0 ||
  667. os_memcmp(pos + sae->tmp->prime_len + sae->tmp->prime_len, prime,
  668. sae->tmp->prime_len) >= 0) {
  669. wpa_printf(MSG_DEBUG, "SAE: Invalid coordinates in peer "
  670. "element");
  671. return WLAN_STATUS_UNSPECIFIED_FAILURE;
  672. }
  673. wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(x)",
  674. pos, sae->tmp->prime_len);
  675. wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(y)",
  676. pos + sae->tmp->prime_len, sae->tmp->prime_len);
  677. crypto_ec_point_deinit(sae->tmp->peer_commit_element_ecc, 0);
  678. sae->tmp->peer_commit_element_ecc =
  679. crypto_ec_point_from_bin(sae->tmp->ec, pos);
  680. if (sae->tmp->peer_commit_element_ecc == NULL)
  681. return WLAN_STATUS_UNSPECIFIED_FAILURE;
  682. if (!crypto_ec_point_is_on_curve(sae->tmp->ec,
  683. sae->tmp->peer_commit_element_ecc)) {
  684. wpa_printf(MSG_DEBUG, "SAE: Peer element is not on curve");
  685. return WLAN_STATUS_UNSPECIFIED_FAILURE;
  686. }
  687. return WLAN_STATUS_SUCCESS;
  688. }
  689. static u16 sae_parse_commit_element_ffc(struct sae_data *sae, const u8 *pos,
  690. const u8 *end)
  691. {
  692. if (pos + sae->tmp->prime_len > end) {
  693. wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
  694. "commit-element");
  695. return WLAN_STATUS_UNSPECIFIED_FAILURE;
  696. }
  697. wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element", pos,
  698. sae->tmp->prime_len);
  699. crypto_bignum_deinit(sae->tmp->peer_commit_element_ffc, 0);
  700. sae->tmp->peer_commit_element_ffc =
  701. crypto_bignum_init_set(pos, sae->tmp->prime_len);
  702. if (sae->tmp->peer_commit_element_ffc == NULL)
  703. return WLAN_STATUS_UNSPECIFIED_FAILURE;
  704. if (crypto_bignum_is_zero(sae->tmp->peer_commit_element_ffc) ||
  705. crypto_bignum_is_one(sae->tmp->peer_commit_element_ffc) ||
  706. crypto_bignum_cmp(sae->tmp->peer_commit_element_ffc,
  707. sae->tmp->prime) >= 0) {
  708. wpa_printf(MSG_DEBUG, "SAE: Invalid peer element");
  709. return WLAN_STATUS_UNSPECIFIED_FAILURE;
  710. }
  711. return WLAN_STATUS_SUCCESS;
  712. }
  713. static u16 sae_parse_commit_element(struct sae_data *sae, const u8 *pos,
  714. const u8 *end)
  715. {
  716. if (sae->tmp->dh)
  717. return sae_parse_commit_element_ffc(sae, pos, end);
  718. return sae_parse_commit_element_ecc(sae, pos, end);
  719. }
  720. u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
  721. const u8 **token, size_t *token_len, int *allowed_groups)
  722. {
  723. const u8 *pos = data, *end = data + len;
  724. u16 res;
  725. /* Check Finite Cyclic Group */
  726. if (pos + 2 > end)
  727. return WLAN_STATUS_UNSPECIFIED_FAILURE;
  728. res = sae_group_allowed(sae, allowed_groups, WPA_GET_LE16(pos));
  729. if (res != WLAN_STATUS_SUCCESS)
  730. return res;
  731. pos += 2;
  732. /* Optional Anti-Clogging Token */
  733. sae_parse_commit_token(sae, &pos, end, token, token_len);
  734. /* commit-scalar */
  735. res = sae_parse_commit_scalar(sae, &pos, end);
  736. if (res != WLAN_STATUS_SUCCESS)
  737. return res;
  738. /* commit-element */
  739. return sae_parse_commit_element(sae, pos, end);
  740. }
  741. static void sae_cn_confirm(struct sae_data *sae, const u8 *sc,
  742. const struct crypto_bignum *scalar1,
  743. const u8 *element1, size_t element1_len,
  744. const struct crypto_bignum *scalar2,
  745. const u8 *element2, size_t element2_len,
  746. u8 *confirm)
  747. {
  748. const u8 *addr[5];
  749. size_t len[5];
  750. u8 scalar_b1[SAE_MAX_PRIME_LEN], scalar_b2[SAE_MAX_PRIME_LEN];
  751. /* Confirm
  752. * CN(key, X, Y, Z, ...) =
  753. * HMAC-SHA256(key, D2OS(X) || D2OS(Y) || D2OS(Z) | ...)
  754. * confirm = CN(KCK, send-confirm, commit-scalar, COMMIT-ELEMENT,
  755. * peer-commit-scalar, PEER-COMMIT-ELEMENT)
  756. * verifier = CN(KCK, peer-send-confirm, peer-commit-scalar,
  757. * PEER-COMMIT-ELEMENT, commit-scalar, COMMIT-ELEMENT)
  758. */
  759. addr[0] = sc;
  760. len[0] = 2;
  761. crypto_bignum_to_bin(scalar1, scalar_b1, sizeof(scalar_b1),
  762. sae->tmp->prime_len);
  763. addr[1] = scalar_b1;
  764. len[1] = sae->tmp->prime_len;
  765. addr[2] = element1;
  766. len[2] = element1_len;
  767. crypto_bignum_to_bin(scalar2, scalar_b2, sizeof(scalar_b2),
  768. sae->tmp->prime_len);
  769. addr[3] = scalar_b2;
  770. len[3] = sae->tmp->prime_len;
  771. addr[4] = element2;
  772. len[4] = element2_len;
  773. hmac_sha256_vector(sae->tmp->kck, sizeof(sae->tmp->kck), 5, addr, len,
  774. confirm);
  775. }
  776. static void sae_cn_confirm_ecc(struct sae_data *sae, const u8 *sc,
  777. const struct crypto_bignum *scalar1,
  778. const struct crypto_ec_point *element1,
  779. const struct crypto_bignum *scalar2,
  780. const struct crypto_ec_point *element2,
  781. u8 *confirm)
  782. {
  783. u8 element_b1[2 * SAE_MAX_ECC_PRIME_LEN];
  784. u8 element_b2[2 * SAE_MAX_ECC_PRIME_LEN];
  785. crypto_ec_point_to_bin(sae->tmp->ec, element1, element_b1,
  786. element_b1 + sae->tmp->prime_len);
  787. crypto_ec_point_to_bin(sae->tmp->ec, element2, element_b2,
  788. element_b2 + sae->tmp->prime_len);
  789. sae_cn_confirm(sae, sc, scalar1, element_b1, 2 * sae->tmp->prime_len,
  790. scalar2, element_b2, 2 * sae->tmp->prime_len, confirm);
  791. }
  792. static void sae_cn_confirm_ffc(struct sae_data *sae, const u8 *sc,
  793. const struct crypto_bignum *scalar1,
  794. const struct crypto_bignum *element1,
  795. const struct crypto_bignum *scalar2,
  796. const struct crypto_bignum *element2,
  797. u8 *confirm)
  798. {
  799. u8 element_b1[SAE_MAX_PRIME_LEN];
  800. u8 element_b2[SAE_MAX_PRIME_LEN];
  801. crypto_bignum_to_bin(element1, element_b1, sizeof(element_b1),
  802. sae->tmp->prime_len);
  803. crypto_bignum_to_bin(element2, element_b2, sizeof(element_b2),
  804. sae->tmp->prime_len);
  805. sae_cn_confirm(sae, sc, scalar1, element_b1, sae->tmp->prime_len,
  806. scalar2, element_b2, sae->tmp->prime_len, confirm);
  807. }
  808. void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
  809. {
  810. const u8 *sc;
  811. /* Send-Confirm */
  812. sc = wpabuf_put(buf, 0);
  813. wpabuf_put_le16(buf, sae->send_confirm);
  814. sae->send_confirm++;
  815. if (sae->tmp->ec)
  816. sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar,
  817. sae->tmp->own_commit_element_ecc,
  818. sae->peer_commit_scalar,
  819. sae->tmp->peer_commit_element_ecc,
  820. wpabuf_put(buf, SHA256_MAC_LEN));
  821. else
  822. sae_cn_confirm_ffc(sae, sc, sae->tmp->own_commit_scalar,
  823. sae->tmp->own_commit_element_ffc,
  824. sae->peer_commit_scalar,
  825. sae->tmp->peer_commit_element_ffc,
  826. wpabuf_put(buf, SHA256_MAC_LEN));
  827. }
  828. int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
  829. {
  830. u8 verifier[SHA256_MAC_LEN];
  831. if (len < 2 + SHA256_MAC_LEN) {
  832. wpa_printf(MSG_DEBUG, "SAE: Too short confirm message");
  833. return -1;
  834. }
  835. wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", WPA_GET_LE16(data));
  836. if (sae->tmp->ec)
  837. sae_cn_confirm_ecc(sae, data, sae->peer_commit_scalar,
  838. sae->tmp->peer_commit_element_ecc,
  839. sae->tmp->own_commit_scalar,
  840. sae->tmp->own_commit_element_ecc,
  841. verifier);
  842. else
  843. sae_cn_confirm_ffc(sae, data, sae->peer_commit_scalar,
  844. sae->tmp->peer_commit_element_ffc,
  845. sae->tmp->own_commit_scalar,
  846. sae->tmp->own_commit_element_ffc,
  847. verifier);
  848. if (os_memcmp(verifier, data + 2, SHA256_MAC_LEN) != 0) {
  849. wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch");
  850. wpa_hexdump(MSG_DEBUG, "SAE: Received confirm",
  851. data + 2, SHA256_MAC_LEN);
  852. wpa_hexdump(MSG_DEBUG, "SAE: Calculated verifier",
  853. verifier, SHA256_MAC_LEN);
  854. return -1;
  855. }
  856. return 0;
  857. }