wpa_common.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  1. /*
  2. * WPA/RSN - Shared functions for supplicant and authenticator
  3. * Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * Alternatively, this software may be distributed under the terms of BSD
  10. * license.
  11. *
  12. * See README and COPYING for more details.
  13. */
  14. #include "includes.h"
  15. #include "common.h"
  16. #include "crypto/md5.h"
  17. #include "crypto/sha1.h"
  18. #include "crypto/sha256.h"
  19. #include "crypto/aes_wrap.h"
  20. #include "crypto/crypto.h"
  21. #include "ieee802_11_defs.h"
  22. #include "defs.h"
  23. #include "wpa_common.h"
  24. /**
  25. * wpa_eapol_key_mic - Calculate EAPOL-Key MIC
  26. * @key: EAPOL-Key Key Confirmation Key (KCK)
  27. * @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*)
  28. * @buf: Pointer to the beginning of the EAPOL header (version field)
  29. * @len: Length of the EAPOL frame (from EAPOL header to the end of the frame)
  30. * @mic: Pointer to the buffer to which the EAPOL-Key MIC is written
  31. * Returns: 0 on success, -1 on failure
  32. *
  33. * Calculate EAPOL-Key MIC for an EAPOL-Key packet. The EAPOL-Key MIC field has
  34. * to be cleared (all zeroes) when calling this function.
  35. *
  36. * Note: 'IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames' has an error in the
  37. * description of the Key MIC calculation. It includes packet data from the
  38. * beginning of the EAPOL-Key header, not EAPOL header. This incorrect change
  39. * happened during final editing of the standard and the correct behavior is
  40. * defined in the last draft (IEEE 802.11i/D10).
  41. */
  42. int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
  43. u8 *mic)
  44. {
  45. u8 hash[SHA1_MAC_LEN];
  46. switch (ver) {
  47. case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
  48. return hmac_md5(key, 16, buf, len, mic);
  49. case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
  50. if (hmac_sha1(key, 16, buf, len, hash))
  51. return -1;
  52. os_memcpy(mic, hash, MD5_MAC_LEN);
  53. break;
  54. #if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
  55. case WPA_KEY_INFO_TYPE_AES_128_CMAC:
  56. return omac1_aes_128(key, buf, len, mic);
  57. #endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
  58. default:
  59. return -1;
  60. }
  61. return 0;
  62. }
  63. /**
  64. * wpa_pmk_to_ptk - Calculate PTK from PMK, addresses, and nonces
  65. * @pmk: Pairwise master key
  66. * @pmk_len: Length of PMK
  67. * @label: Label to use in derivation
  68. * @addr1: AA or SA
  69. * @addr2: SA or AA
  70. * @nonce1: ANonce or SNonce
  71. * @nonce2: SNonce or ANonce
  72. * @ptk: Buffer for pairwise transient key
  73. * @ptk_len: Length of PTK
  74. * @use_sha256: Whether to use SHA256-based KDF
  75. *
  76. * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
  77. * PTK = PRF-X(PMK, "Pairwise key expansion",
  78. * Min(AA, SA) || Max(AA, SA) ||
  79. * Min(ANonce, SNonce) || Max(ANonce, SNonce))
  80. *
  81. * STK = PRF-X(SMK, "Peer key expansion",
  82. * Min(MAC_I, MAC_P) || Max(MAC_I, MAC_P) ||
  83. * Min(INonce, PNonce) || Max(INonce, PNonce))
  84. */
  85. void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
  86. const u8 *addr1, const u8 *addr2,
  87. const u8 *nonce1, const u8 *nonce2,
  88. u8 *ptk, size_t ptk_len, int use_sha256)
  89. {
  90. u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN];
  91. if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) {
  92. os_memcpy(data, addr1, ETH_ALEN);
  93. os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN);
  94. } else {
  95. os_memcpy(data, addr2, ETH_ALEN);
  96. os_memcpy(data + ETH_ALEN, addr1, ETH_ALEN);
  97. }
  98. if (os_memcmp(nonce1, nonce2, WPA_NONCE_LEN) < 0) {
  99. os_memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN);
  100. os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2,
  101. WPA_NONCE_LEN);
  102. } else {
  103. os_memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN);
  104. os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1,
  105. WPA_NONCE_LEN);
  106. }
  107. #ifdef CONFIG_IEEE80211W
  108. if (use_sha256)
  109. sha256_prf(pmk, pmk_len, label, data, sizeof(data),
  110. ptk, ptk_len);
  111. else
  112. #endif /* CONFIG_IEEE80211W */
  113. sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk,
  114. ptk_len);
  115. wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR,
  116. MAC2STR(addr1), MAC2STR(addr2));
  117. wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len);
  118. wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", ptk, ptk_len);
  119. }
  120. #ifdef CONFIG_IEEE80211R
  121. int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr,
  122. u8 transaction_seqnum, const u8 *mdie, size_t mdie_len,
  123. const u8 *ftie, size_t ftie_len,
  124. const u8 *rsnie, size_t rsnie_len,
  125. const u8 *ric, size_t ric_len, u8 *mic)
  126. {
  127. u8 *buf, *pos;
  128. size_t buf_len;
  129. buf_len = 2 * ETH_ALEN + 1 + mdie_len + ftie_len + rsnie_len + ric_len;
  130. buf = os_malloc(buf_len);
  131. if (buf == NULL)
  132. return -1;
  133. pos = buf;
  134. os_memcpy(pos, sta_addr, ETH_ALEN);
  135. pos += ETH_ALEN;
  136. os_memcpy(pos, ap_addr, ETH_ALEN);
  137. pos += ETH_ALEN;
  138. *pos++ = transaction_seqnum;
  139. if (rsnie) {
  140. os_memcpy(pos, rsnie, rsnie_len);
  141. pos += rsnie_len;
  142. }
  143. if (mdie) {
  144. os_memcpy(pos, mdie, mdie_len);
  145. pos += mdie_len;
  146. }
  147. if (ftie) {
  148. struct rsn_ftie *_ftie;
  149. os_memcpy(pos, ftie, ftie_len);
  150. if (ftie_len < 2 + sizeof(*_ftie)) {
  151. os_free(buf);
  152. return -1;
  153. }
  154. _ftie = (struct rsn_ftie *) (pos + 2);
  155. os_memset(_ftie->mic, 0, sizeof(_ftie->mic));
  156. pos += ftie_len;
  157. }
  158. if (ric) {
  159. os_memcpy(pos, ric, ric_len);
  160. pos += ric_len;
  161. }
  162. wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", buf, pos - buf);
  163. if (omac1_aes_128(kck, buf, pos - buf, mic)) {
  164. os_free(buf);
  165. return -1;
  166. }
  167. os_free(buf);
  168. return 0;
  169. }
  170. #endif /* CONFIG_IEEE80211R */
  171. #ifndef CONFIG_NO_WPA2
  172. static int rsn_selector_to_bitfield(const u8 *s)
  173. {
  174. if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE)
  175. return WPA_CIPHER_NONE;
  176. if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP40)
  177. return WPA_CIPHER_WEP40;
  178. if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_TKIP)
  179. return WPA_CIPHER_TKIP;
  180. if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP)
  181. return WPA_CIPHER_CCMP;
  182. if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP104)
  183. return WPA_CIPHER_WEP104;
  184. #ifdef CONFIG_IEEE80211W
  185. if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC)
  186. return WPA_CIPHER_AES_128_CMAC;
  187. #endif /* CONFIG_IEEE80211W */
  188. return 0;
  189. }
  190. static int rsn_key_mgmt_to_bitfield(const u8 *s)
  191. {
  192. if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_UNSPEC_802_1X)
  193. return WPA_KEY_MGMT_IEEE8021X;
  194. if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X)
  195. return WPA_KEY_MGMT_PSK;
  196. #ifdef CONFIG_IEEE80211R
  197. if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X)
  198. return WPA_KEY_MGMT_FT_IEEE8021X;
  199. if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK)
  200. return WPA_KEY_MGMT_FT_PSK;
  201. #endif /* CONFIG_IEEE80211R */
  202. #ifdef CONFIG_IEEE80211W
  203. if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256)
  204. return WPA_KEY_MGMT_IEEE8021X_SHA256;
  205. if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256)
  206. return WPA_KEY_MGMT_PSK_SHA256;
  207. #endif /* CONFIG_IEEE80211W */
  208. return 0;
  209. }
  210. #endif /* CONFIG_NO_WPA2 */
  211. /**
  212. * wpa_parse_wpa_ie_rsn - Parse RSN IE
  213. * @rsn_ie: Buffer containing RSN IE
  214. * @rsn_ie_len: RSN IE buffer length (including IE number and length octets)
  215. * @data: Pointer to structure that will be filled in with parsed data
  216. * Returns: 0 on success, <0 on failure
  217. */
  218. int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
  219. struct wpa_ie_data *data)
  220. {
  221. #ifndef CONFIG_NO_WPA2
  222. const struct rsn_ie_hdr *hdr;
  223. const u8 *pos;
  224. int left;
  225. int i, count;
  226. os_memset(data, 0, sizeof(*data));
  227. data->proto = WPA_PROTO_RSN;
  228. data->pairwise_cipher = WPA_CIPHER_CCMP;
  229. data->group_cipher = WPA_CIPHER_CCMP;
  230. data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
  231. data->capabilities = 0;
  232. data->pmkid = NULL;
  233. data->num_pmkid = 0;
  234. #ifdef CONFIG_IEEE80211W
  235. data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
  236. #else /* CONFIG_IEEE80211W */
  237. data->mgmt_group_cipher = 0;
  238. #endif /* CONFIG_IEEE80211W */
  239. if (rsn_ie_len == 0) {
  240. /* No RSN IE - fail silently */
  241. return -1;
  242. }
  243. if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) {
  244. wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
  245. __func__, (unsigned long) rsn_ie_len);
  246. return -1;
  247. }
  248. hdr = (const struct rsn_ie_hdr *) rsn_ie;
  249. if (hdr->elem_id != WLAN_EID_RSN ||
  250. hdr->len != rsn_ie_len - 2 ||
  251. WPA_GET_LE16(hdr->version) != RSN_VERSION) {
  252. wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
  253. __func__);
  254. return -2;
  255. }
  256. pos = (const u8 *) (hdr + 1);
  257. left = rsn_ie_len - sizeof(*hdr);
  258. if (left >= RSN_SELECTOR_LEN) {
  259. data->group_cipher = rsn_selector_to_bitfield(pos);
  260. #ifdef CONFIG_IEEE80211W
  261. if (data->group_cipher == WPA_CIPHER_AES_128_CMAC) {
  262. wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as group "
  263. "cipher", __func__);
  264. return -1;
  265. }
  266. #endif /* CONFIG_IEEE80211W */
  267. pos += RSN_SELECTOR_LEN;
  268. left -= RSN_SELECTOR_LEN;
  269. } else if (left > 0) {
  270. wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
  271. __func__, left);
  272. return -3;
  273. }
  274. if (left >= 2) {
  275. data->pairwise_cipher = 0;
  276. count = WPA_GET_LE16(pos);
  277. pos += 2;
  278. left -= 2;
  279. if (count == 0 || left < count * RSN_SELECTOR_LEN) {
  280. wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
  281. "count %u left %u", __func__, count, left);
  282. return -4;
  283. }
  284. for (i = 0; i < count; i++) {
  285. data->pairwise_cipher |= rsn_selector_to_bitfield(pos);
  286. pos += RSN_SELECTOR_LEN;
  287. left -= RSN_SELECTOR_LEN;
  288. }
  289. #ifdef CONFIG_IEEE80211W
  290. if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) {
  291. wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as "
  292. "pairwise cipher", __func__);
  293. return -1;
  294. }
  295. #endif /* CONFIG_IEEE80211W */
  296. } else if (left == 1) {
  297. wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
  298. __func__);
  299. return -5;
  300. }
  301. if (left >= 2) {
  302. data->key_mgmt = 0;
  303. count = WPA_GET_LE16(pos);
  304. pos += 2;
  305. left -= 2;
  306. if (count == 0 || left < count * RSN_SELECTOR_LEN) {
  307. wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
  308. "count %u left %u", __func__, count, left);
  309. return -6;
  310. }
  311. for (i = 0; i < count; i++) {
  312. data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos);
  313. pos += RSN_SELECTOR_LEN;
  314. left -= RSN_SELECTOR_LEN;
  315. }
  316. } else if (left == 1) {
  317. wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
  318. __func__);
  319. return -7;
  320. }
  321. if (left >= 2) {
  322. data->capabilities = WPA_GET_LE16(pos);
  323. pos += 2;
  324. left -= 2;
  325. }
  326. if (left >= 2) {
  327. data->num_pmkid = WPA_GET_LE16(pos);
  328. pos += 2;
  329. left -= 2;
  330. if (left < (int) data->num_pmkid * PMKID_LEN) {
  331. wpa_printf(MSG_DEBUG, "%s: PMKID underflow "
  332. "(num_pmkid=%lu left=%d)",
  333. __func__, (unsigned long) data->num_pmkid,
  334. left);
  335. data->num_pmkid = 0;
  336. return -9;
  337. } else {
  338. data->pmkid = pos;
  339. pos += data->num_pmkid * PMKID_LEN;
  340. left -= data->num_pmkid * PMKID_LEN;
  341. }
  342. }
  343. #ifdef CONFIG_IEEE80211W
  344. if (left >= 4) {
  345. data->mgmt_group_cipher = rsn_selector_to_bitfield(pos);
  346. if (data->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) {
  347. wpa_printf(MSG_DEBUG, "%s: Unsupported management "
  348. "group cipher 0x%x", __func__,
  349. data->mgmt_group_cipher);
  350. return -10;
  351. }
  352. pos += RSN_SELECTOR_LEN;
  353. left -= RSN_SELECTOR_LEN;
  354. }
  355. #endif /* CONFIG_IEEE80211W */
  356. if (left > 0) {
  357. wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored",
  358. __func__, left);
  359. }
  360. return 0;
  361. #else /* CONFIG_NO_WPA2 */
  362. return -1;
  363. #endif /* CONFIG_NO_WPA2 */
  364. }
  365. #ifdef CONFIG_IEEE80211R
  366. /**
  367. * wpa_derive_pmk_r0 - Derive PMK-R0 and PMKR0Name
  368. *
  369. * IEEE Std 802.11r-2008 - 8.5.1.5.3
  370. */
  371. void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
  372. const u8 *ssid, size_t ssid_len,
  373. const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
  374. const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name)
  375. {
  376. u8 buf[1 + WPA_MAX_SSID_LEN + MOBILITY_DOMAIN_ID_LEN + 1 +
  377. FT_R0KH_ID_MAX_LEN + ETH_ALEN];
  378. u8 *pos, r0_key_data[48], hash[32];
  379. const u8 *addr[2];
  380. size_t len[2];
  381. /*
  382. * R0-Key-Data = KDF-384(XXKey, "FT-R0",
  383. * SSIDlength || SSID || MDID || R0KHlength ||
  384. * R0KH-ID || S0KH-ID)
  385. * XXKey is either the second 256 bits of MSK or PSK.
  386. * PMK-R0 = L(R0-Key-Data, 0, 256)
  387. * PMK-R0Name-Salt = L(R0-Key-Data, 256, 128)
  388. */
  389. if (ssid_len > WPA_MAX_SSID_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN)
  390. return;
  391. pos = buf;
  392. *pos++ = ssid_len;
  393. os_memcpy(pos, ssid, ssid_len);
  394. pos += ssid_len;
  395. os_memcpy(pos, mdid, MOBILITY_DOMAIN_ID_LEN);
  396. pos += MOBILITY_DOMAIN_ID_LEN;
  397. *pos++ = r0kh_id_len;
  398. os_memcpy(pos, r0kh_id, r0kh_id_len);
  399. pos += r0kh_id_len;
  400. os_memcpy(pos, s0kh_id, ETH_ALEN);
  401. pos += ETH_ALEN;
  402. sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
  403. r0_key_data, sizeof(r0_key_data));
  404. os_memcpy(pmk_r0, r0_key_data, PMK_LEN);
  405. /*
  406. * PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt)
  407. */
  408. addr[0] = (const u8 *) "FT-R0N";
  409. len[0] = 6;
  410. addr[1] = r0_key_data + PMK_LEN;
  411. len[1] = 16;
  412. sha256_vector(2, addr, len, hash);
  413. os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN);
  414. }
  415. /**
  416. * wpa_derive_pmk_r1_name - Derive PMKR1Name
  417. *
  418. * IEEE Std 802.11r-2008 - 8.5.1.5.4
  419. */
  420. void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
  421. const u8 *s1kh_id, u8 *pmk_r1_name)
  422. {
  423. u8 hash[32];
  424. const u8 *addr[4];
  425. size_t len[4];
  426. /*
  427. * PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name ||
  428. * R1KH-ID || S1KH-ID))
  429. */
  430. addr[0] = (const u8 *) "FT-R1N";
  431. len[0] = 6;
  432. addr[1] = pmk_r0_name;
  433. len[1] = WPA_PMK_NAME_LEN;
  434. addr[2] = r1kh_id;
  435. len[2] = FT_R1KH_ID_LEN;
  436. addr[3] = s1kh_id;
  437. len[3] = ETH_ALEN;
  438. sha256_vector(4, addr, len, hash);
  439. os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN);
  440. }
  441. /**
  442. * wpa_derive_pmk_r1 - Derive PMK-R1 and PMKR1Name from PMK-R0
  443. *
  444. * IEEE Std 802.11r-2008 - 8.5.1.5.4
  445. */
  446. void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name,
  447. const u8 *r1kh_id, const u8 *s1kh_id,
  448. u8 *pmk_r1, u8 *pmk_r1_name)
  449. {
  450. u8 buf[FT_R1KH_ID_LEN + ETH_ALEN];
  451. u8 *pos;
  452. /* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */
  453. pos = buf;
  454. os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN);
  455. pos += FT_R1KH_ID_LEN;
  456. os_memcpy(pos, s1kh_id, ETH_ALEN);
  457. pos += ETH_ALEN;
  458. sha256_prf(pmk_r0, PMK_LEN, "FT-R1", buf, pos - buf, pmk_r1, PMK_LEN);
  459. wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id, pmk_r1_name);
  460. }
  461. /**
  462. * wpa_pmk_r1_to_ptk - Derive PTK and PTKName from PMK-R1
  463. *
  464. * IEEE Std 802.11r-2008 - 8.5.1.5.5
  465. */
  466. void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
  467. const u8 *sta_addr, const u8 *bssid,
  468. const u8 *pmk_r1_name,
  469. u8 *ptk, size_t ptk_len, u8 *ptk_name)
  470. {
  471. u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN];
  472. u8 *pos, hash[32];
  473. const u8 *addr[6];
  474. size_t len[6];
  475. /*
  476. * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce ||
  477. * BSSID || STA-ADDR)
  478. */
  479. pos = buf;
  480. os_memcpy(pos, snonce, WPA_NONCE_LEN);
  481. pos += WPA_NONCE_LEN;
  482. os_memcpy(pos, anonce, WPA_NONCE_LEN);
  483. pos += WPA_NONCE_LEN;
  484. os_memcpy(pos, bssid, ETH_ALEN);
  485. pos += ETH_ALEN;
  486. os_memcpy(pos, sta_addr, ETH_ALEN);
  487. pos += ETH_ALEN;
  488. sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, ptk, ptk_len);
  489. /*
  490. * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce ||
  491. * ANonce || BSSID || STA-ADDR))
  492. */
  493. addr[0] = pmk_r1_name;
  494. len[0] = WPA_PMK_NAME_LEN;
  495. addr[1] = (const u8 *) "FT-PTKN";
  496. len[1] = 7;
  497. addr[2] = snonce;
  498. len[2] = WPA_NONCE_LEN;
  499. addr[3] = anonce;
  500. len[3] = WPA_NONCE_LEN;
  501. addr[4] = bssid;
  502. len[4] = ETH_ALEN;
  503. addr[5] = sta_addr;
  504. len[5] = ETH_ALEN;
  505. sha256_vector(6, addr, len, hash);
  506. os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN);
  507. }
  508. #endif /* CONFIG_IEEE80211R */
  509. /**
  510. * rsn_pmkid - Calculate PMK identifier
  511. * @pmk: Pairwise master key
  512. * @pmk_len: Length of pmk in bytes
  513. * @aa: Authenticator address
  514. * @spa: Supplicant address
  515. * @pmkid: Buffer for PMKID
  516. * @use_sha256: Whether to use SHA256-based KDF
  517. *
  518. * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
  519. * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA)
  520. */
  521. void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
  522. u8 *pmkid, int use_sha256)
  523. {
  524. char *title = "PMK Name";
  525. const u8 *addr[3];
  526. const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
  527. unsigned char hash[SHA256_MAC_LEN];
  528. addr[0] = (u8 *) title;
  529. addr[1] = aa;
  530. addr[2] = spa;
  531. #ifdef CONFIG_IEEE80211W
  532. if (use_sha256)
  533. hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash);
  534. else
  535. #endif /* CONFIG_IEEE80211W */
  536. hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash);
  537. os_memcpy(pmkid, hash, PMKID_LEN);
  538. }
  539. /**
  540. * wpa_cipher_txt - Convert cipher suite to a text string
  541. * @cipher: Cipher suite (WPA_CIPHER_* enum)
  542. * Returns: Pointer to a text string of the cipher suite name
  543. */
  544. const char * wpa_cipher_txt(int cipher)
  545. {
  546. switch (cipher) {
  547. case WPA_CIPHER_NONE:
  548. return "NONE";
  549. case WPA_CIPHER_WEP40:
  550. return "WEP-40";
  551. case WPA_CIPHER_WEP104:
  552. return "WEP-104";
  553. case WPA_CIPHER_TKIP:
  554. return "TKIP";
  555. case WPA_CIPHER_CCMP:
  556. return "CCMP";
  557. case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP:
  558. return "CCMP+TKIP";
  559. default:
  560. return "UNKNOWN";
  561. }
  562. }
  563. /**
  564. * wpa_key_mgmt_txt - Convert key management suite to a text string
  565. * @key_mgmt: Key management suite (WPA_KEY_MGMT_* enum)
  566. * @proto: WPA/WPA2 version (WPA_PROTO_*)
  567. * Returns: Pointer to a text string of the key management suite name
  568. */
  569. const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
  570. {
  571. switch (key_mgmt) {
  572. case WPA_KEY_MGMT_IEEE8021X:
  573. if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
  574. return "WPA2+WPA/IEEE 802.1X/EAP";
  575. return proto == WPA_PROTO_RSN ?
  576. "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP";
  577. case WPA_KEY_MGMT_PSK:
  578. if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
  579. return "WPA2-PSK+WPA-PSK";
  580. return proto == WPA_PROTO_RSN ?
  581. "WPA2-PSK" : "WPA-PSK";
  582. case WPA_KEY_MGMT_NONE:
  583. return "NONE";
  584. case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
  585. return "IEEE 802.1X (no WPA)";
  586. #ifdef CONFIG_IEEE80211R
  587. case WPA_KEY_MGMT_FT_IEEE8021X:
  588. return "FT-EAP";
  589. case WPA_KEY_MGMT_FT_PSK:
  590. return "FT-PSK";
  591. #endif /* CONFIG_IEEE80211R */
  592. #ifdef CONFIG_IEEE80211W
  593. case WPA_KEY_MGMT_IEEE8021X_SHA256:
  594. return "WPA2-EAP-SHA256";
  595. case WPA_KEY_MGMT_PSK_SHA256:
  596. return "WPA2-PSK-SHA256";
  597. #endif /* CONFIG_IEEE80211W */
  598. default:
  599. return "UNKNOWN";
  600. }
  601. }
  602. int wpa_compare_rsn_ie(int ft_initial_assoc,
  603. const u8 *ie1, size_t ie1len,
  604. const u8 *ie2, size_t ie2len)
  605. {
  606. if (ie1 == NULL || ie2 == NULL)
  607. return -1;
  608. if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0)
  609. return 0; /* identical IEs */
  610. #ifdef CONFIG_IEEE80211R
  611. if (ft_initial_assoc) {
  612. struct wpa_ie_data ie1d, ie2d;
  613. /*
  614. * The PMKID-List in RSN IE is different between Beacon/Probe
  615. * Response/(Re)Association Request frames and EAPOL-Key
  616. * messages in FT initial mobility domain association. Allow
  617. * for this, but verify that other parts of the RSN IEs are
  618. * identical.
  619. */
  620. if (wpa_parse_wpa_ie_rsn(ie1, ie1len, &ie1d) < 0 ||
  621. wpa_parse_wpa_ie_rsn(ie2, ie2len, &ie2d) < 0)
  622. return -1;
  623. if (ie1d.proto == ie2d.proto &&
  624. ie1d.pairwise_cipher == ie2d.pairwise_cipher &&
  625. ie1d.group_cipher == ie2d.group_cipher &&
  626. ie1d.key_mgmt == ie2d.key_mgmt &&
  627. ie1d.capabilities == ie2d.capabilities &&
  628. ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher)
  629. return 0;
  630. }
  631. #endif /* CONFIG_IEEE80211R */
  632. return -1;
  633. }
  634. #ifdef CONFIG_IEEE80211R
  635. int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
  636. {
  637. u8 *start, *end, *rpos, *rend;
  638. int added = 0;
  639. start = ies;
  640. end = ies + ies_len;
  641. while (start < end) {
  642. if (*start == WLAN_EID_RSN)
  643. break;
  644. start += 2 + start[1];
  645. }
  646. if (start >= end) {
  647. wpa_printf(MSG_ERROR, "FT: Could not find RSN IE in "
  648. "IEs data");
  649. return -1;
  650. }
  651. wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification",
  652. start, 2 + start[1]);
  653. /* Find start of PMKID-Count */
  654. rpos = start + 2;
  655. rend = rpos + start[1];
  656. /* Skip Version and Group Data Cipher Suite */
  657. rpos += 2 + 4;
  658. /* Skip Pairwise Cipher Suite Count and List */
  659. rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
  660. /* Skip AKM Suite Count and List */
  661. rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
  662. if (rpos == rend) {
  663. /* Add RSN Capabilities */
  664. os_memmove(rpos + 2, rpos, end - rpos);
  665. *rpos++ = 0;
  666. *rpos++ = 0;
  667. } else {
  668. /* Skip RSN Capabilities */
  669. rpos += 2;
  670. if (rpos > rend) {
  671. wpa_printf(MSG_ERROR, "FT: Could not parse RSN IE in "
  672. "IEs data");
  673. return -1;
  674. }
  675. }
  676. if (rpos == rend) {
  677. /* No PMKID-Count field included; add it */
  678. os_memmove(rpos + 2 + PMKID_LEN, rpos, end - rpos);
  679. WPA_PUT_LE16(rpos, 1);
  680. rpos += 2;
  681. os_memcpy(rpos, pmkid, PMKID_LEN);
  682. added += 2 + PMKID_LEN;
  683. start[1] += 2 + PMKID_LEN;
  684. } else {
  685. /* PMKID-Count was included; use it */
  686. if (WPA_GET_LE16(rpos) != 0) {
  687. wpa_printf(MSG_ERROR, "FT: Unexpected PMKID "
  688. "in RSN IE in EAPOL-Key data");
  689. return -1;
  690. }
  691. WPA_PUT_LE16(rpos, 1);
  692. rpos += 2;
  693. os_memmove(rpos + PMKID_LEN, rpos, end - rpos);
  694. os_memcpy(rpos, pmkid, PMKID_LEN);
  695. added += PMKID_LEN;
  696. start[1] += PMKID_LEN;
  697. }
  698. wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification "
  699. "(PMKID inserted)", start, 2 + start[1]);
  700. return added;
  701. }
  702. #endif /* CONFIG_IEEE80211R */