PageRenderTime 53ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/external/wpa_supplicant_8/src/rsn_supp/wpa_ie.c

https://gitlab.com/brian0218/rk3188_r-box_android4.2.2_sdk
C | 435 lines | 344 code | 47 blank | 44 comment | 117 complexity | 6399d69f8feea8d0aa33dcf75065ff71 MD5 | raw file
  1. /*
  2. * wpa_supplicant - WPA/RSN IE and KDE processing
  3. * Copyright (c) 2003-2008, 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 "wpa.h"
  11. #include "pmksa_cache.h"
  12. #include "common/ieee802_11_defs.h"
  13. #include "wpa_i.h"
  14. #include "wpa_ie.h"
  15. /**
  16. * wpa_parse_wpa_ie - Parse WPA/RSN IE
  17. * @wpa_ie: Pointer to WPA or RSN IE
  18. * @wpa_ie_len: Length of the WPA/RSN IE
  19. * @data: Pointer to data area for parsing results
  20. * Returns: 0 on success, -1 on failure
  21. *
  22. * Parse the contents of WPA or RSN IE and write the parsed data into data.
  23. */
  24. int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
  25. struct wpa_ie_data *data)
  26. {
  27. if (wpa_ie_len >= 1 && wpa_ie[0] == WLAN_EID_RSN)
  28. return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
  29. else
  30. return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data);
  31. }
  32. static int wpa_gen_wpa_ie_wpa(u8 *wpa_ie, size_t wpa_ie_len,
  33. int pairwise_cipher, int group_cipher,
  34. int key_mgmt)
  35. {
  36. u8 *pos;
  37. struct wpa_ie_hdr *hdr;
  38. u32 suite;
  39. if (wpa_ie_len < sizeof(*hdr) + WPA_SELECTOR_LEN +
  40. 2 + WPA_SELECTOR_LEN + 2 + WPA_SELECTOR_LEN)
  41. return -1;
  42. hdr = (struct wpa_ie_hdr *) wpa_ie;
  43. hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC;
  44. RSN_SELECTOR_PUT(hdr->oui, WPA_OUI_TYPE);
  45. WPA_PUT_LE16(hdr->version, WPA_VERSION);
  46. pos = (u8 *) (hdr + 1);
  47. suite = wpa_cipher_to_suite(WPA_PROTO_WPA, group_cipher);
  48. if (suite == 0) {
  49. wpa_printf(MSG_WARNING, "Invalid group cipher (%d).",
  50. group_cipher);
  51. return -1;
  52. }
  53. RSN_SELECTOR_PUT(pos, suite);
  54. pos += WPA_SELECTOR_LEN;
  55. *pos++ = 1;
  56. *pos++ = 0;
  57. suite = wpa_cipher_to_suite(WPA_PROTO_WPA, pairwise_cipher);
  58. if (suite == 0 ||
  59. (!wpa_cipher_valid_pairwise(pairwise_cipher) &&
  60. pairwise_cipher != WPA_CIPHER_NONE)) {
  61. wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).",
  62. pairwise_cipher);
  63. return -1;
  64. }
  65. RSN_SELECTOR_PUT(pos, suite);
  66. pos += WPA_SELECTOR_LEN;
  67. *pos++ = 1;
  68. *pos++ = 0;
  69. if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) {
  70. RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X);
  71. } else if (key_mgmt == WPA_KEY_MGMT_PSK) {
  72. RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X);
  73. } else if (key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
  74. RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_NONE);
  75. } else {
  76. wpa_printf(MSG_WARNING, "Invalid key management type (%d).",
  77. key_mgmt);
  78. return -1;
  79. }
  80. pos += WPA_SELECTOR_LEN;
  81. /* WPA Capabilities; use defaults, so no need to include it */
  82. hdr->len = (pos - wpa_ie) - 2;
  83. WPA_ASSERT((size_t) (pos - wpa_ie) <= wpa_ie_len);
  84. return pos - wpa_ie;
  85. }
  86. static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len,
  87. int pairwise_cipher, int group_cipher,
  88. int key_mgmt, int mgmt_group_cipher,
  89. struct wpa_sm *sm)
  90. {
  91. #ifndef CONFIG_NO_WPA2
  92. u8 *pos;
  93. struct rsn_ie_hdr *hdr;
  94. u16 capab;
  95. u32 suite;
  96. if (rsn_ie_len < sizeof(*hdr) + RSN_SELECTOR_LEN +
  97. 2 + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN + 2 +
  98. (sm->cur_pmksa ? 2 + PMKID_LEN : 0)) {
  99. wpa_printf(MSG_DEBUG, "RSN: Too short IE buffer (%lu bytes)",
  100. (unsigned long) rsn_ie_len);
  101. return -1;
  102. }
  103. hdr = (struct rsn_ie_hdr *) rsn_ie;
  104. hdr->elem_id = WLAN_EID_RSN;
  105. WPA_PUT_LE16(hdr->version, RSN_VERSION);
  106. pos = (u8 *) (hdr + 1);
  107. suite = wpa_cipher_to_suite(WPA_PROTO_RSN, group_cipher);
  108. if (suite == 0) {
  109. wpa_printf(MSG_WARNING, "Invalid group cipher (%d).",
  110. group_cipher);
  111. return -1;
  112. }
  113. RSN_SELECTOR_PUT(pos, suite);
  114. pos += RSN_SELECTOR_LEN;
  115. *pos++ = 1;
  116. *pos++ = 0;
  117. suite = wpa_cipher_to_suite(WPA_PROTO_RSN, pairwise_cipher);
  118. if (suite == 0 ||
  119. (!wpa_cipher_valid_pairwise(pairwise_cipher) &&
  120. pairwise_cipher != WPA_CIPHER_NONE)) {
  121. wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).",
  122. pairwise_cipher);
  123. return -1;
  124. }
  125. RSN_SELECTOR_PUT(pos, suite);
  126. pos += RSN_SELECTOR_LEN;
  127. *pos++ = 1;
  128. *pos++ = 0;
  129. if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) {
  130. RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X);
  131. } else if (key_mgmt == WPA_KEY_MGMT_PSK) {
  132. RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X);
  133. #ifdef CONFIG_IEEE80211R
  134. } else if (key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) {
  135. RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
  136. } else if (key_mgmt == WPA_KEY_MGMT_FT_PSK) {
  137. RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
  138. #endif /* CONFIG_IEEE80211R */
  139. #ifdef CONFIG_IEEE80211W
  140. } else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SHA256) {
  141. RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256);
  142. } else if (key_mgmt == WPA_KEY_MGMT_PSK_SHA256) {
  143. RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256);
  144. #endif /* CONFIG_IEEE80211W */
  145. } else {
  146. wpa_printf(MSG_WARNING, "Invalid key management type (%d).",
  147. key_mgmt);
  148. return -1;
  149. }
  150. pos += RSN_SELECTOR_LEN;
  151. /* RSN Capabilities */
  152. capab = 0;
  153. #ifdef CONFIG_IEEE80211W
  154. if (sm->mfp)
  155. capab |= WPA_CAPABILITY_MFPC;
  156. if (sm->mfp == 2)
  157. capab |= WPA_CAPABILITY_MFPR;
  158. #endif /* CONFIG_IEEE80211W */
  159. WPA_PUT_LE16(pos, capab);
  160. pos += 2;
  161. if (sm->cur_pmksa) {
  162. /* PMKID Count (2 octets, little endian) */
  163. *pos++ = 1;
  164. *pos++ = 0;
  165. /* PMKID */
  166. os_memcpy(pos, sm->cur_pmksa->pmkid, PMKID_LEN);
  167. pos += PMKID_LEN;
  168. }
  169. #ifdef CONFIG_IEEE80211W
  170. if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) {
  171. if (!sm->cur_pmksa) {
  172. /* PMKID Count */
  173. WPA_PUT_LE16(pos, 0);
  174. pos += 2;
  175. }
  176. /* Management Group Cipher Suite */
  177. RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
  178. pos += RSN_SELECTOR_LEN;
  179. }
  180. #endif /* CONFIG_IEEE80211W */
  181. hdr->len = (pos - rsn_ie) - 2;
  182. WPA_ASSERT((size_t) (pos - rsn_ie) <= rsn_ie_len);
  183. return pos - rsn_ie;
  184. #else /* CONFIG_NO_WPA2 */
  185. return -1;
  186. #endif /* CONFIG_NO_WPA2 */
  187. }
  188. /**
  189. * wpa_gen_wpa_ie - Generate WPA/RSN IE based on current security policy
  190. * @sm: Pointer to WPA state machine data from wpa_sm_init()
  191. * @wpa_ie: Pointer to memory area for the generated WPA/RSN IE
  192. * @wpa_ie_len: Maximum length of the generated WPA/RSN IE
  193. * Returns: Length of the generated WPA/RSN IE or -1 on failure
  194. */
  195. int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len)
  196. {
  197. if (sm->proto == WPA_PROTO_RSN)
  198. return wpa_gen_wpa_ie_rsn(wpa_ie, wpa_ie_len,
  199. sm->pairwise_cipher,
  200. sm->group_cipher,
  201. sm->key_mgmt, sm->mgmt_group_cipher,
  202. sm);
  203. else
  204. return wpa_gen_wpa_ie_wpa(wpa_ie, wpa_ie_len,
  205. sm->pairwise_cipher,
  206. sm->group_cipher,
  207. sm->key_mgmt);
  208. }
  209. /**
  210. * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs
  211. * @pos: Pointer to the IE header
  212. * @end: Pointer to the end of the Key Data buffer
  213. * @ie: Pointer to parsed IE data
  214. * Returns: 0 on success, 1 if end mark is found, -1 on failure
  215. */
  216. static int wpa_parse_generic(const u8 *pos, const u8 *end,
  217. struct wpa_eapol_ie_parse *ie)
  218. {
  219. if (pos[1] == 0)
  220. return 1;
  221. if (pos[1] >= 6 &&
  222. RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE &&
  223. pos[2 + WPA_SELECTOR_LEN] == 1 &&
  224. pos[2 + WPA_SELECTOR_LEN + 1] == 0) {
  225. ie->wpa_ie = pos;
  226. ie->wpa_ie_len = pos[1] + 2;
  227. wpa_hexdump(MSG_DEBUG, "WPA: WPA IE in EAPOL-Key",
  228. ie->wpa_ie, ie->wpa_ie_len);
  229. return 0;
  230. }
  231. if (pos + 1 + RSN_SELECTOR_LEN < end &&
  232. pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN &&
  233. RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) {
  234. ie->pmkid = pos + 2 + RSN_SELECTOR_LEN;
  235. wpa_hexdump(MSG_DEBUG, "WPA: PMKID in EAPOL-Key",
  236. pos, pos[1] + 2);
  237. return 0;
  238. }
  239. if (pos[1] > RSN_SELECTOR_LEN + 2 &&
  240. RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) {
  241. ie->gtk = pos + 2 + RSN_SELECTOR_LEN;
  242. ie->gtk_len = pos[1] - RSN_SELECTOR_LEN;
  243. wpa_hexdump_key(MSG_DEBUG, "WPA: GTK in EAPOL-Key",
  244. pos, pos[1] + 2);
  245. return 0;
  246. }
  247. if (pos[1] > RSN_SELECTOR_LEN + 2 &&
  248. RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) {
  249. ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN;
  250. ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN;
  251. wpa_hexdump(MSG_DEBUG, "WPA: MAC Address in EAPOL-Key",
  252. pos, pos[1] + 2);
  253. return 0;
  254. }
  255. #ifdef CONFIG_PEERKEY
  256. if (pos[1] > RSN_SELECTOR_LEN + 2 &&
  257. RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_SMK) {
  258. ie->smk = pos + 2 + RSN_SELECTOR_LEN;
  259. ie->smk_len = pos[1] - RSN_SELECTOR_LEN;
  260. wpa_hexdump_key(MSG_DEBUG, "WPA: SMK in EAPOL-Key",
  261. pos, pos[1] + 2);
  262. return 0;
  263. }
  264. if (pos[1] > RSN_SELECTOR_LEN + 2 &&
  265. RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_NONCE) {
  266. ie->nonce = pos + 2 + RSN_SELECTOR_LEN;
  267. ie->nonce_len = pos[1] - RSN_SELECTOR_LEN;
  268. wpa_hexdump(MSG_DEBUG, "WPA: Nonce in EAPOL-Key",
  269. pos, pos[1] + 2);
  270. return 0;
  271. }
  272. if (pos[1] > RSN_SELECTOR_LEN + 2 &&
  273. RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_LIFETIME) {
  274. ie->lifetime = pos + 2 + RSN_SELECTOR_LEN;
  275. ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN;
  276. wpa_hexdump(MSG_DEBUG, "WPA: Lifetime in EAPOL-Key",
  277. pos, pos[1] + 2);
  278. return 0;
  279. }
  280. if (pos[1] > RSN_SELECTOR_LEN + 2 &&
  281. RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_ERROR) {
  282. ie->error = pos + 2 + RSN_SELECTOR_LEN;
  283. ie->error_len = pos[1] - RSN_SELECTOR_LEN;
  284. wpa_hexdump(MSG_DEBUG, "WPA: Error in EAPOL-Key",
  285. pos, pos[1] + 2);
  286. return 0;
  287. }
  288. #endif /* CONFIG_PEERKEY */
  289. #ifdef CONFIG_IEEE80211W
  290. if (pos[1] > RSN_SELECTOR_LEN + 2 &&
  291. RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) {
  292. ie->igtk = pos + 2 + RSN_SELECTOR_LEN;
  293. ie->igtk_len = pos[1] - RSN_SELECTOR_LEN;
  294. wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK in EAPOL-Key",
  295. pos, pos[1] + 2);
  296. return 0;
  297. }
  298. #endif /* CONFIG_IEEE80211W */
  299. return 0;
  300. }
  301. /**
  302. * wpa_supplicant_parse_ies - Parse EAPOL-Key Key Data IEs
  303. * @buf: Pointer to the Key Data buffer
  304. * @len: Key Data Length
  305. * @ie: Pointer to parsed IE data
  306. * Returns: 0 on success, -1 on failure
  307. */
  308. int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
  309. struct wpa_eapol_ie_parse *ie)
  310. {
  311. const u8 *pos, *end;
  312. int ret = 0;
  313. os_memset(ie, 0, sizeof(*ie));
  314. for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) {
  315. if (pos[0] == 0xdd &&
  316. ((pos == buf + len - 1) || pos[1] == 0)) {
  317. /* Ignore padding */
  318. break;
  319. }
  320. if (pos + 2 + pos[1] > end) {
  321. wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data "
  322. "underflow (ie=%d len=%d pos=%d)",
  323. pos[0], pos[1], (int) (pos - buf));
  324. wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data",
  325. buf, len);
  326. ret = -1;
  327. break;
  328. }
  329. if (*pos == WLAN_EID_RSN) {
  330. ie->rsn_ie = pos;
  331. ie->rsn_ie_len = pos[1] + 2;
  332. wpa_hexdump(MSG_DEBUG, "WPA: RSN IE in EAPOL-Key",
  333. ie->rsn_ie, ie->rsn_ie_len);
  334. } else if (*pos == WLAN_EID_MOBILITY_DOMAIN) {
  335. ie->mdie = pos;
  336. ie->mdie_len = pos[1] + 2;
  337. wpa_hexdump(MSG_DEBUG, "WPA: MDIE in EAPOL-Key",
  338. ie->mdie, ie->mdie_len);
  339. } else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) {
  340. ie->ftie = pos;
  341. ie->ftie_len = pos[1] + 2;
  342. wpa_hexdump(MSG_DEBUG, "WPA: FTIE in EAPOL-Key",
  343. ie->ftie, ie->ftie_len);
  344. } else if (*pos == WLAN_EID_TIMEOUT_INTERVAL && pos[1] >= 5) {
  345. if (pos[2] == WLAN_TIMEOUT_REASSOC_DEADLINE) {
  346. ie->reassoc_deadline = pos;
  347. wpa_hexdump(MSG_DEBUG, "WPA: Reassoc Deadline "
  348. "in EAPOL-Key",
  349. ie->reassoc_deadline, pos[1] + 2);
  350. } else if (pos[2] == WLAN_TIMEOUT_KEY_LIFETIME) {
  351. ie->key_lifetime = pos;
  352. wpa_hexdump(MSG_DEBUG, "WPA: KeyLifetime "
  353. "in EAPOL-Key",
  354. ie->key_lifetime, pos[1] + 2);
  355. } else {
  356. wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized "
  357. "EAPOL-Key Key Data IE",
  358. pos, 2 + pos[1]);
  359. }
  360. } else if (*pos == WLAN_EID_LINK_ID) {
  361. if (pos[1] >= 18) {
  362. ie->lnkid = pos;
  363. ie->lnkid_len = pos[1] + 2;
  364. }
  365. } else if (*pos == WLAN_EID_EXT_CAPAB) {
  366. ie->ext_capab = pos;
  367. ie->ext_capab_len = pos[1] + 2;
  368. } else if (*pos == WLAN_EID_SUPP_RATES) {
  369. ie->supp_rates = pos;
  370. ie->supp_rates_len = pos[1] + 2;
  371. } else if (*pos == WLAN_EID_EXT_SUPP_RATES) {
  372. ie->ext_supp_rates = pos;
  373. ie->ext_supp_rates_len = pos[1] + 2;
  374. } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
  375. ret = wpa_parse_generic(pos, end, ie);
  376. if (ret < 0)
  377. break;
  378. if (ret > 0) {
  379. ret = 0;
  380. break;
  381. }
  382. } else {
  383. wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key "
  384. "Key Data IE", pos, 2 + pos[1]);
  385. }
  386. }
  387. return ret;
  388. }