wpa_ft.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. /*
  2. * WPA Supplicant - IEEE 802.11r - Fast BSS Transition
  3. * Copyright (c) 2006-2015, 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/aes_wrap.h"
  11. #include "crypto/random.h"
  12. #include "common/ieee802_11_defs.h"
  13. #include "common/ieee802_11_common.h"
  14. #include "wpa.h"
  15. #include "wpa_i.h"
  16. #ifdef CONFIG_IEEE80211R
  17. int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
  18. const struct wpa_eapol_key *key, struct wpa_ptk *ptk)
  19. {
  20. u8 ptk_name[WPA_PMK_NAME_LEN];
  21. const u8 *anonce = key->key_nonce;
  22. if (sm->xxkey_len == 0) {
  23. wpa_printf(MSG_DEBUG, "FT: XXKey not available for key "
  24. "derivation");
  25. return -1;
  26. }
  27. wpa_derive_pmk_r0(sm->xxkey, sm->xxkey_len, sm->ssid,
  28. sm->ssid_len, sm->mobility_domain,
  29. sm->r0kh_id, sm->r0kh_id_len, sm->own_addr,
  30. sm->pmk_r0, sm->pmk_r0_name);
  31. wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", sm->pmk_r0, PMK_LEN);
  32. wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name",
  33. sm->pmk_r0_name, WPA_PMK_NAME_LEN);
  34. wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_name, sm->r1kh_id,
  35. sm->own_addr, sm->pmk_r1, sm->pmk_r1_name);
  36. wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, PMK_LEN);
  37. wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name,
  38. WPA_PMK_NAME_LEN);
  39. return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, anonce, sm->own_addr,
  40. sm->bssid, sm->pmk_r1_name, ptk, ptk_name,
  41. sm->key_mgmt, sm->pairwise_cipher);
  42. }
  43. /**
  44. * wpa_sm_set_ft_params - Set FT (IEEE 802.11r) parameters
  45. * @sm: Pointer to WPA state machine data from wpa_sm_init()
  46. * @ies: Association Response IEs or %NULL to clear FT parameters
  47. * @ies_len: Length of ies buffer in octets
  48. * Returns: 0 on success, -1 on failure
  49. */
  50. int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len)
  51. {
  52. struct wpa_ft_ies ft;
  53. if (sm == NULL)
  54. return 0;
  55. if (wpa_ft_parse_ies(ies, ies_len, &ft) < 0)
  56. return -1;
  57. if (ft.mdie && ft.mdie_len < MOBILITY_DOMAIN_ID_LEN + 1)
  58. return -1;
  59. if (ft.mdie) {
  60. wpa_hexdump(MSG_DEBUG, "FT: Mobility domain",
  61. ft.mdie, MOBILITY_DOMAIN_ID_LEN);
  62. os_memcpy(sm->mobility_domain, ft.mdie,
  63. MOBILITY_DOMAIN_ID_LEN);
  64. sm->mdie_ft_capab = ft.mdie[MOBILITY_DOMAIN_ID_LEN];
  65. wpa_printf(MSG_DEBUG, "FT: Capability and Policy: 0x%02x",
  66. sm->mdie_ft_capab);
  67. } else
  68. os_memset(sm->mobility_domain, 0, MOBILITY_DOMAIN_ID_LEN);
  69. if (ft.r0kh_id) {
  70. wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID",
  71. ft.r0kh_id, ft.r0kh_id_len);
  72. os_memcpy(sm->r0kh_id, ft.r0kh_id, ft.r0kh_id_len);
  73. sm->r0kh_id_len = ft.r0kh_id_len;
  74. } else {
  75. /* FIX: When should R0KH-ID be cleared? We need to keep the
  76. * old R0KH-ID in order to be able to use this during FT. */
  77. /*
  78. * os_memset(sm->r0kh_id, 0, FT_R0KH_ID_LEN);
  79. * sm->r0kh_id_len = 0;
  80. */
  81. }
  82. if (ft.r1kh_id) {
  83. wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID",
  84. ft.r1kh_id, FT_R1KH_ID_LEN);
  85. os_memcpy(sm->r1kh_id, ft.r1kh_id, FT_R1KH_ID_LEN);
  86. } else
  87. os_memset(sm->r1kh_id, 0, FT_R1KH_ID_LEN);
  88. os_free(sm->assoc_resp_ies);
  89. sm->assoc_resp_ies = os_malloc(ft.mdie_len + 2 + ft.ftie_len + 2);
  90. if (sm->assoc_resp_ies) {
  91. u8 *pos = sm->assoc_resp_ies;
  92. if (ft.mdie) {
  93. os_memcpy(pos, ft.mdie - 2, ft.mdie_len + 2);
  94. pos += ft.mdie_len + 2;
  95. }
  96. if (ft.ftie) {
  97. os_memcpy(pos, ft.ftie - 2, ft.ftie_len + 2);
  98. pos += ft.ftie_len + 2;
  99. }
  100. sm->assoc_resp_ies_len = pos - sm->assoc_resp_ies;
  101. wpa_hexdump(MSG_DEBUG, "FT: Stored MDIE and FTIE from "
  102. "(Re)Association Response",
  103. sm->assoc_resp_ies, sm->assoc_resp_ies_len);
  104. }
  105. return 0;
  106. }
  107. /**
  108. * wpa_ft_gen_req_ies - Generate FT (IEEE 802.11r) IEs for Auth/ReAssoc Request
  109. * @sm: Pointer to WPA state machine data from wpa_sm_init()
  110. * @len: Buffer for returning the length of the IEs
  111. * @anonce: ANonce or %NULL if not yet available
  112. * @pmk_name: PMKR0Name or PMKR1Name to be added into the RSN IE PMKID List
  113. * @kck: 128-bit KCK for MIC or %NULL if no MIC is used
  114. * @kck_len: KCK length in octets
  115. * @target_ap: Target AP address
  116. * @ric_ies: Optional IE(s), e.g., WMM TSPEC(s), for RIC-Request or %NULL
  117. * @ric_ies_len: Length of ric_ies buffer in octets
  118. * @ap_mdie: Mobility Domain IE from the target AP
  119. * Returns: Pointer to buffer with IEs or %NULL on failure
  120. *
  121. * Caller is responsible for freeing the returned buffer with os_free();
  122. */
  123. static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
  124. const u8 *anonce, const u8 *pmk_name,
  125. const u8 *kck, size_t kck_len,
  126. const u8 *target_ap,
  127. const u8 *ric_ies, size_t ric_ies_len,
  128. const u8 *ap_mdie)
  129. {
  130. size_t buf_len;
  131. u8 *buf, *pos, *ftie_len, *ftie_pos;
  132. struct rsn_mdie *mdie;
  133. struct rsn_ftie *ftie;
  134. struct rsn_ie_hdr *rsnie;
  135. u16 capab;
  136. sm->ft_completed = 0;
  137. buf_len = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) +
  138. 2 + sm->r0kh_id_len + ric_ies_len + 100;
  139. buf = os_zalloc(buf_len);
  140. if (buf == NULL)
  141. return NULL;
  142. pos = buf;
  143. /* RSNIE[PMKR0Name/PMKR1Name] */
  144. rsnie = (struct rsn_ie_hdr *) pos;
  145. rsnie->elem_id = WLAN_EID_RSN;
  146. WPA_PUT_LE16(rsnie->version, RSN_VERSION);
  147. pos = (u8 *) (rsnie + 1);
  148. /* Group Suite Selector */
  149. if (!wpa_cipher_valid_group(sm->group_cipher)) {
  150. wpa_printf(MSG_WARNING, "FT: Invalid group cipher (%d)",
  151. sm->group_cipher);
  152. os_free(buf);
  153. return NULL;
  154. }
  155. RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN,
  156. sm->group_cipher));
  157. pos += RSN_SELECTOR_LEN;
  158. /* Pairwise Suite Count */
  159. WPA_PUT_LE16(pos, 1);
  160. pos += 2;
  161. /* Pairwise Suite List */
  162. if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) {
  163. wpa_printf(MSG_WARNING, "FT: Invalid pairwise cipher (%d)",
  164. sm->pairwise_cipher);
  165. os_free(buf);
  166. return NULL;
  167. }
  168. RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN,
  169. sm->pairwise_cipher));
  170. pos += RSN_SELECTOR_LEN;
  171. /* Authenticated Key Management Suite Count */
  172. WPA_PUT_LE16(pos, 1);
  173. pos += 2;
  174. /* Authenticated Key Management Suite List */
  175. if (sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X)
  176. RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
  177. else if (sm->key_mgmt == WPA_KEY_MGMT_FT_PSK)
  178. RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
  179. else if (sm->key_mgmt == WPA_KEY_MGMT_FT_SAE)
  180. RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
  181. else {
  182. wpa_printf(MSG_WARNING, "FT: Invalid key management type (%d)",
  183. sm->key_mgmt);
  184. os_free(buf);
  185. return NULL;
  186. }
  187. pos += RSN_SELECTOR_LEN;
  188. /* RSN Capabilities */
  189. capab = 0;
  190. #ifdef CONFIG_IEEE80211W
  191. if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC)
  192. capab |= WPA_CAPABILITY_MFPC;
  193. #endif /* CONFIG_IEEE80211W */
  194. WPA_PUT_LE16(pos, capab);
  195. pos += 2;
  196. /* PMKID Count */
  197. WPA_PUT_LE16(pos, 1);
  198. pos += 2;
  199. /* PMKID List [PMKR0Name/PMKR1Name] */
  200. os_memcpy(pos, pmk_name, WPA_PMK_NAME_LEN);
  201. pos += WPA_PMK_NAME_LEN;
  202. #ifdef CONFIG_IEEE80211W
  203. if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) {
  204. /* Management Group Cipher Suite */
  205. RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
  206. pos += RSN_SELECTOR_LEN;
  207. }
  208. #endif /* CONFIG_IEEE80211W */
  209. rsnie->len = (pos - (u8 *) rsnie) - 2;
  210. /* MDIE */
  211. *pos++ = WLAN_EID_MOBILITY_DOMAIN;
  212. *pos++ = sizeof(*mdie);
  213. mdie = (struct rsn_mdie *) pos;
  214. pos += sizeof(*mdie);
  215. os_memcpy(mdie->mobility_domain, sm->mobility_domain,
  216. MOBILITY_DOMAIN_ID_LEN);
  217. mdie->ft_capab = ap_mdie && ap_mdie[1] >= 3 ? ap_mdie[4] :
  218. sm->mdie_ft_capab;
  219. /* FTIE[SNonce, [R1KH-ID,] R0KH-ID ] */
  220. ftie_pos = pos;
  221. *pos++ = WLAN_EID_FAST_BSS_TRANSITION;
  222. ftie_len = pos++;
  223. ftie = (struct rsn_ftie *) pos;
  224. pos += sizeof(*ftie);
  225. os_memcpy(ftie->snonce, sm->snonce, WPA_NONCE_LEN);
  226. if (anonce)
  227. os_memcpy(ftie->anonce, anonce, WPA_NONCE_LEN);
  228. if (kck) {
  229. /* R1KH-ID sub-element in third FT message */
  230. *pos++ = FTIE_SUBELEM_R1KH_ID;
  231. *pos++ = FT_R1KH_ID_LEN;
  232. os_memcpy(pos, sm->r1kh_id, FT_R1KH_ID_LEN);
  233. pos += FT_R1KH_ID_LEN;
  234. }
  235. /* R0KH-ID sub-element */
  236. *pos++ = FTIE_SUBELEM_R0KH_ID;
  237. *pos++ = sm->r0kh_id_len;
  238. os_memcpy(pos, sm->r0kh_id, sm->r0kh_id_len);
  239. pos += sm->r0kh_id_len;
  240. *ftie_len = pos - ftie_len - 1;
  241. if (ric_ies) {
  242. /* RIC Request */
  243. os_memcpy(pos, ric_ies, ric_ies_len);
  244. pos += ric_ies_len;
  245. }
  246. if (kck) {
  247. /*
  248. * IEEE Std 802.11r-2008, 11A.8.4
  249. * MIC shall be calculated over:
  250. * non-AP STA MAC address
  251. * Target AP MAC address
  252. * Transaction seq number (5 for ReassocReq, 3 otherwise)
  253. * RSN IE
  254. * MDIE
  255. * FTIE (with MIC field set to 0)
  256. * RIC-Request (if present)
  257. */
  258. /* Information element count */
  259. ftie->mic_control[1] = 3 + ieee802_11_ie_count(ric_ies,
  260. ric_ies_len);
  261. if (wpa_ft_mic(kck, kck_len, sm->own_addr, target_ap, 5,
  262. ((u8 *) mdie) - 2, 2 + sizeof(*mdie),
  263. ftie_pos, 2 + *ftie_len,
  264. (u8 *) rsnie, 2 + rsnie->len, ric_ies,
  265. ric_ies_len, ftie->mic) < 0) {
  266. wpa_printf(MSG_INFO, "FT: Failed to calculate MIC");
  267. os_free(buf);
  268. return NULL;
  269. }
  270. }
  271. *len = pos - buf;
  272. return buf;
  273. }
  274. static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid)
  275. {
  276. int keylen;
  277. enum wpa_alg alg;
  278. u8 null_rsc[6] = { 0, 0, 0, 0, 0, 0 };
  279. wpa_printf(MSG_DEBUG, "FT: Installing PTK to the driver.");
  280. if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) {
  281. wpa_printf(MSG_WARNING, "FT: Unsupported pairwise cipher %d",
  282. sm->pairwise_cipher);
  283. return -1;
  284. }
  285. alg = wpa_cipher_to_alg(sm->pairwise_cipher);
  286. keylen = wpa_cipher_key_len(sm->pairwise_cipher);
  287. if (wpa_sm_set_key(sm, alg, bssid, 0, 1, null_rsc,
  288. sizeof(null_rsc), (u8 *) sm->ptk.tk, keylen) < 0) {
  289. wpa_printf(MSG_WARNING, "FT: Failed to set PTK to the driver");
  290. return -1;
  291. }
  292. return 0;
  293. }
  294. /**
  295. * wpa_ft_prepare_auth_request - Generate over-the-air auth request
  296. * @sm: Pointer to WPA state machine data from wpa_sm_init()
  297. * @mdie: Target AP MDIE
  298. * Returns: 0 on success, -1 on failure
  299. */
  300. int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie)
  301. {
  302. u8 *ft_ies;
  303. size_t ft_ies_len;
  304. /* Generate a new SNonce */
  305. if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) {
  306. wpa_printf(MSG_INFO, "FT: Failed to generate a new SNonce");
  307. return -1;
  308. }
  309. ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name,
  310. NULL, 0, sm->bssid, NULL, 0, mdie);
  311. if (ft_ies) {
  312. wpa_sm_update_ft_ies(sm, sm->mobility_domain,
  313. ft_ies, ft_ies_len);
  314. os_free(ft_ies);
  315. }
  316. return 0;
  317. }
  318. int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
  319. int ft_action, const u8 *target_ap,
  320. const u8 *ric_ies, size_t ric_ies_len)
  321. {
  322. u8 *ft_ies;
  323. size_t ft_ies_len;
  324. struct wpa_ft_ies parse;
  325. struct rsn_mdie *mdie;
  326. struct rsn_ftie *ftie;
  327. u8 ptk_name[WPA_PMK_NAME_LEN];
  328. int ret;
  329. const u8 *bssid;
  330. wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len);
  331. wpa_hexdump(MSG_DEBUG, "FT: RIC IEs", ric_ies, ric_ies_len);
  332. if (ft_action) {
  333. if (!sm->over_the_ds_in_progress) {
  334. wpa_printf(MSG_DEBUG, "FT: No over-the-DS in progress "
  335. "- drop FT Action Response");
  336. return -1;
  337. }
  338. if (os_memcmp(target_ap, sm->target_ap, ETH_ALEN) != 0) {
  339. wpa_printf(MSG_DEBUG, "FT: No over-the-DS in progress "
  340. "with this Target AP - drop FT Action "
  341. "Response");
  342. return -1;
  343. }
  344. }
  345. if (!wpa_key_mgmt_ft(sm->key_mgmt)) {
  346. wpa_printf(MSG_DEBUG, "FT: Reject FT IEs since FT is not "
  347. "enabled for this connection");
  348. return -1;
  349. }
  350. if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
  351. wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs");
  352. return -1;
  353. }
  354. mdie = (struct rsn_mdie *) parse.mdie;
  355. if (mdie == NULL || parse.mdie_len < sizeof(*mdie) ||
  356. os_memcmp(mdie->mobility_domain, sm->mobility_domain,
  357. MOBILITY_DOMAIN_ID_LEN) != 0) {
  358. wpa_printf(MSG_DEBUG, "FT: Invalid MDIE");
  359. return -1;
  360. }
  361. ftie = (struct rsn_ftie *) parse.ftie;
  362. if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {
  363. wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
  364. return -1;
  365. }
  366. if (os_memcmp(ftie->snonce, sm->snonce, WPA_NONCE_LEN) != 0) {
  367. wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE");
  368. wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
  369. ftie->snonce, WPA_NONCE_LEN);
  370. wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce",
  371. sm->snonce, WPA_NONCE_LEN);
  372. return -1;
  373. }
  374. if (parse.r0kh_id == NULL) {
  375. wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE");
  376. return -1;
  377. }
  378. if (parse.r0kh_id_len != sm->r0kh_id_len ||
  379. os_memcmp_const(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0)
  380. {
  381. wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with "
  382. "the current R0KH-ID");
  383. wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE",
  384. parse.r0kh_id, parse.r0kh_id_len);
  385. wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID",
  386. sm->r0kh_id, sm->r0kh_id_len);
  387. return -1;
  388. }
  389. if (parse.r1kh_id == NULL) {
  390. wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE");
  391. return -1;
  392. }
  393. if (parse.rsn_pmkid == NULL ||
  394. os_memcmp_const(parse.rsn_pmkid, sm->pmk_r0_name, WPA_PMK_NAME_LEN))
  395. {
  396. wpa_printf(MSG_DEBUG, "FT: No matching PMKR0Name (PMKID) in "
  397. "RSNIE");
  398. return -1;
  399. }
  400. os_memcpy(sm->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN);
  401. wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID", sm->r1kh_id, FT_R1KH_ID_LEN);
  402. wpa_hexdump(MSG_DEBUG, "FT: SNonce", sm->snonce, WPA_NONCE_LEN);
  403. wpa_hexdump(MSG_DEBUG, "FT: ANonce", ftie->anonce, WPA_NONCE_LEN);
  404. os_memcpy(sm->anonce, ftie->anonce, WPA_NONCE_LEN);
  405. wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_name, sm->r1kh_id,
  406. sm->own_addr, sm->pmk_r1, sm->pmk_r1_name);
  407. wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, PMK_LEN);
  408. wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name",
  409. sm->pmk_r1_name, WPA_PMK_NAME_LEN);
  410. bssid = target_ap;
  411. if (wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, ftie->anonce,
  412. sm->own_addr, bssid, sm->pmk_r1_name, &sm->ptk,
  413. ptk_name, sm->key_mgmt, sm->pairwise_cipher) < 0)
  414. return -1;
  415. ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, ftie->anonce,
  416. sm->pmk_r1_name,
  417. sm->ptk.kck, sm->ptk.kck_len, bssid,
  418. ric_ies, ric_ies_len,
  419. parse.mdie ? parse.mdie - 2 : NULL);
  420. if (ft_ies) {
  421. wpa_sm_update_ft_ies(sm, sm->mobility_domain,
  422. ft_ies, ft_ies_len);
  423. os_free(ft_ies);
  424. }
  425. wpa_sm_mark_authenticated(sm, bssid);
  426. ret = wpa_ft_install_ptk(sm, bssid);
  427. if (ret) {
  428. /*
  429. * Some drivers do not support key configuration when we are
  430. * not associated with the target AP. Work around this by
  431. * trying again after the following reassociation gets
  432. * completed.
  433. */
  434. wpa_printf(MSG_DEBUG, "FT: Failed to set PTK prior to "
  435. "association - try again after reassociation");
  436. sm->set_ptk_after_assoc = 1;
  437. } else
  438. sm->set_ptk_after_assoc = 0;
  439. sm->ft_completed = 1;
  440. if (ft_action) {
  441. /*
  442. * The caller is expected trigger re-association with the
  443. * Target AP.
  444. */
  445. os_memcpy(sm->bssid, target_ap, ETH_ALEN);
  446. }
  447. return 0;
  448. }
  449. int wpa_ft_is_completed(struct wpa_sm *sm)
  450. {
  451. if (sm == NULL)
  452. return 0;
  453. if (!wpa_key_mgmt_ft(sm->key_mgmt))
  454. return 0;
  455. return sm->ft_completed;
  456. }
  457. void wpa_reset_ft_completed(struct wpa_sm *sm)
  458. {
  459. if (sm != NULL)
  460. sm->ft_completed = 0;
  461. }
  462. static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
  463. size_t gtk_elem_len)
  464. {
  465. u8 gtk[32];
  466. int keyidx;
  467. enum wpa_alg alg;
  468. size_t gtk_len, keylen, rsc_len;
  469. if (gtk_elem == NULL) {
  470. wpa_printf(MSG_DEBUG, "FT: No GTK included in FTIE");
  471. return 0;
  472. }
  473. wpa_hexdump_key(MSG_DEBUG, "FT: Received GTK in Reassoc Resp",
  474. gtk_elem, gtk_elem_len);
  475. if (gtk_elem_len < 11 + 24 || (gtk_elem_len - 11) % 8 ||
  476. gtk_elem_len - 19 > sizeof(gtk)) {
  477. wpa_printf(MSG_DEBUG, "FT: Invalid GTK sub-elem "
  478. "length %lu", (unsigned long) gtk_elem_len);
  479. return -1;
  480. }
  481. gtk_len = gtk_elem_len - 19;
  482. if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, gtk_len / 8, gtk_elem + 11,
  483. gtk)) {
  484. wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not "
  485. "decrypt GTK");
  486. return -1;
  487. }
  488. keylen = wpa_cipher_key_len(sm->group_cipher);
  489. rsc_len = wpa_cipher_rsc_len(sm->group_cipher);
  490. alg = wpa_cipher_to_alg(sm->group_cipher);
  491. if (alg == WPA_ALG_NONE) {
  492. wpa_printf(MSG_WARNING, "WPA: Unsupported Group Cipher %d",
  493. sm->group_cipher);
  494. return -1;
  495. }
  496. if (gtk_len < keylen) {
  497. wpa_printf(MSG_DEBUG, "FT: Too short GTK in FTIE");
  498. return -1;
  499. }
  500. /* Key Info[2] | Key Length[1] | RSC[8] | Key[5..32]. */
  501. keyidx = WPA_GET_LE16(gtk_elem) & 0x03;
  502. if (gtk_elem[2] != keylen) {
  503. wpa_printf(MSG_DEBUG, "FT: GTK length mismatch: received %d "
  504. "negotiated %lu",
  505. gtk_elem[2], (unsigned long) keylen);
  506. return -1;
  507. }
  508. wpa_hexdump_key(MSG_DEBUG, "FT: GTK from Reassoc Resp", gtk, keylen);
  509. if (sm->group_cipher == WPA_CIPHER_TKIP) {
  510. /* Swap Tx/Rx keys for Michael MIC */
  511. u8 tmp[8];
  512. os_memcpy(tmp, gtk + 16, 8);
  513. os_memcpy(gtk + 16, gtk + 24, 8);
  514. os_memcpy(gtk + 24, tmp, 8);
  515. }
  516. if (wpa_sm_set_key(sm, alg, broadcast_ether_addr, keyidx, 0,
  517. gtk_elem + 3, rsc_len, gtk, keylen) < 0) {
  518. wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to the "
  519. "driver.");
  520. return -1;
  521. }
  522. return 0;
  523. }
  524. #ifdef CONFIG_IEEE80211W
  525. static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem,
  526. size_t igtk_elem_len)
  527. {
  528. u8 igtk[WPA_IGTK_LEN];
  529. u16 keyidx;
  530. if (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC)
  531. return 0;
  532. if (igtk_elem == NULL) {
  533. wpa_printf(MSG_DEBUG, "FT: No IGTK included in FTIE");
  534. return 0;
  535. }
  536. wpa_hexdump_key(MSG_DEBUG, "FT: Received IGTK in Reassoc Resp",
  537. igtk_elem, igtk_elem_len);
  538. if (igtk_elem_len != 2 + 6 + 1 + WPA_IGTK_LEN + 8) {
  539. wpa_printf(MSG_DEBUG, "FT: Invalid IGTK sub-elem "
  540. "length %lu", (unsigned long) igtk_elem_len);
  541. return -1;
  542. }
  543. if (igtk_elem[8] != WPA_IGTK_LEN) {
  544. wpa_printf(MSG_DEBUG, "FT: Invalid IGTK sub-elem Key Length "
  545. "%d", igtk_elem[8]);
  546. return -1;
  547. }
  548. if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, WPA_IGTK_LEN / 8,
  549. igtk_elem + 9, igtk)) {
  550. wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not "
  551. "decrypt IGTK");
  552. return -1;
  553. }
  554. /* KeyID[2] | IPN[6] | Key Length[1] | Key[16+8] */
  555. keyidx = WPA_GET_LE16(igtk_elem);
  556. wpa_hexdump_key(MSG_DEBUG, "FT: IGTK from Reassoc Resp", igtk,
  557. WPA_IGTK_LEN);
  558. if (wpa_sm_set_key(sm, WPA_ALG_IGTK, broadcast_ether_addr, keyidx, 0,
  559. igtk_elem + 2, 6, igtk, WPA_IGTK_LEN) < 0) {
  560. wpa_printf(MSG_WARNING, "WPA: Failed to set IGTK to the "
  561. "driver.");
  562. return -1;
  563. }
  564. return 0;
  565. }
  566. #endif /* CONFIG_IEEE80211W */
  567. int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
  568. size_t ies_len, const u8 *src_addr)
  569. {
  570. struct wpa_ft_ies parse;
  571. struct rsn_mdie *mdie;
  572. struct rsn_ftie *ftie;
  573. unsigned int count;
  574. u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
  575. wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len);
  576. if (!wpa_key_mgmt_ft(sm->key_mgmt)) {
  577. wpa_printf(MSG_DEBUG, "FT: Reject FT IEs since FT is not "
  578. "enabled for this connection");
  579. return -1;
  580. }
  581. if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
  582. wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs");
  583. return -1;
  584. }
  585. mdie = (struct rsn_mdie *) parse.mdie;
  586. if (mdie == NULL || parse.mdie_len < sizeof(*mdie) ||
  587. os_memcmp(mdie->mobility_domain, sm->mobility_domain,
  588. MOBILITY_DOMAIN_ID_LEN) != 0) {
  589. wpa_printf(MSG_DEBUG, "FT: Invalid MDIE");
  590. return -1;
  591. }
  592. ftie = (struct rsn_ftie *) parse.ftie;
  593. if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {
  594. wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
  595. return -1;
  596. }
  597. if (os_memcmp(ftie->snonce, sm->snonce, WPA_NONCE_LEN) != 0) {
  598. wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE");
  599. wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
  600. ftie->snonce, WPA_NONCE_LEN);
  601. wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce",
  602. sm->snonce, WPA_NONCE_LEN);
  603. return -1;
  604. }
  605. if (os_memcmp(ftie->anonce, sm->anonce, WPA_NONCE_LEN) != 0) {
  606. wpa_printf(MSG_DEBUG, "FT: ANonce mismatch in FTIE");
  607. wpa_hexdump(MSG_DEBUG, "FT: Received ANonce",
  608. ftie->anonce, WPA_NONCE_LEN);
  609. wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce",
  610. sm->anonce, WPA_NONCE_LEN);
  611. return -1;
  612. }
  613. if (parse.r0kh_id == NULL) {
  614. wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE");
  615. return -1;
  616. }
  617. if (parse.r0kh_id_len != sm->r0kh_id_len ||
  618. os_memcmp_const(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0)
  619. {
  620. wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with "
  621. "the current R0KH-ID");
  622. wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE",
  623. parse.r0kh_id, parse.r0kh_id_len);
  624. wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID",
  625. sm->r0kh_id, sm->r0kh_id_len);
  626. return -1;
  627. }
  628. if (parse.r1kh_id == NULL) {
  629. wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE");
  630. return -1;
  631. }
  632. if (os_memcmp_const(parse.r1kh_id, sm->r1kh_id, FT_R1KH_ID_LEN) != 0) {
  633. wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in "
  634. "ReassocResp");
  635. return -1;
  636. }
  637. if (parse.rsn_pmkid == NULL ||
  638. os_memcmp_const(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN))
  639. {
  640. wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in "
  641. "RSNIE (pmkid=%d)", !!parse.rsn_pmkid);
  642. return -1;
  643. }
  644. count = 3;
  645. if (parse.ric)
  646. count += ieee802_11_ie_count(parse.ric, parse.ric_len);
  647. if (ftie->mic_control[1] != count) {
  648. wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC "
  649. "Control: received %u expected %u",
  650. ftie->mic_control[1], count);
  651. return -1;
  652. }
  653. if (wpa_ft_mic(sm->ptk.kck, sm->ptk.kck_len, sm->own_addr, src_addr, 6,
  654. parse.mdie - 2, parse.mdie_len + 2,
  655. parse.ftie - 2, parse.ftie_len + 2,
  656. parse.rsn - 2, parse.rsn_len + 2,
  657. parse.ric, parse.ric_len,
  658. mic) < 0) {
  659. wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");
  660. return -1;
  661. }
  662. if (os_memcmp_const(mic, ftie->mic, 16) != 0) {
  663. wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE");
  664. wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", ftie->mic, 16);
  665. wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16);
  666. return -1;
  667. }
  668. if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0)
  669. return -1;
  670. #ifdef CONFIG_IEEE80211W
  671. if (wpa_ft_process_igtk_subelem(sm, parse.igtk, parse.igtk_len) < 0)
  672. return -1;
  673. #endif /* CONFIG_IEEE80211W */
  674. if (sm->set_ptk_after_assoc) {
  675. wpa_printf(MSG_DEBUG, "FT: Try to set PTK again now that we "
  676. "are associated");
  677. if (wpa_ft_install_ptk(sm, src_addr) < 0)
  678. return -1;
  679. sm->set_ptk_after_assoc = 0;
  680. }
  681. if (parse.ric) {
  682. wpa_hexdump(MSG_MSGDUMP, "FT: RIC Response",
  683. parse.ric, parse.ric_len);
  684. /* TODO: parse response and inform driver about results when
  685. * using wpa_supplicant SME */
  686. }
  687. wpa_printf(MSG_DEBUG, "FT: Completed successfully");
  688. return 0;
  689. }
  690. /**
  691. * wpa_ft_start_over_ds - Generate over-the-DS auth request
  692. * @sm: Pointer to WPA state machine data from wpa_sm_init()
  693. * @target_ap: Target AP Address
  694. * @mdie: Mobility Domain IE from the target AP
  695. * Returns: 0 on success, -1 on failure
  696. */
  697. int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap,
  698. const u8 *mdie)
  699. {
  700. u8 *ft_ies;
  701. size_t ft_ies_len;
  702. wpa_printf(MSG_DEBUG, "FT: Request over-the-DS with " MACSTR,
  703. MAC2STR(target_ap));
  704. /* Generate a new SNonce */
  705. if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) {
  706. wpa_printf(MSG_INFO, "FT: Failed to generate a new SNonce");
  707. return -1;
  708. }
  709. ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name,
  710. NULL, 0, target_ap, NULL, 0, mdie);
  711. if (ft_ies) {
  712. sm->over_the_ds_in_progress = 1;
  713. os_memcpy(sm->target_ap, target_ap, ETH_ALEN);
  714. wpa_sm_send_ft_action(sm, 1, target_ap, ft_ies, ft_ies_len);
  715. os_free(ft_ies);
  716. }
  717. return 0;
  718. }
  719. #endif /* CONFIG_IEEE80211R */