rx_tdls.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. /*
  2. * Received Data frame processing for TDLS packets
  3. * Copyright (c) 2010, 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 "utils/includes.h"
  15. #include "utils/common.h"
  16. #include "crypto/sha256.h"
  17. #include "crypto/crypto.h"
  18. #include "crypto/aes_wrap.h"
  19. #include "common/ieee802_11_defs.h"
  20. #include "common/ieee802_11_common.h"
  21. #include "wlantest.h"
  22. static struct wlantest_tdls * get_tdls(struct wlantest *wt, const u8 *linkid)
  23. {
  24. struct wlantest_bss *bss;
  25. struct wlantest_sta *init, *resp;
  26. struct wlantest_tdls *tdls;
  27. bss = bss_find(wt, linkid);
  28. if (bss == NULL)
  29. return NULL;
  30. init = sta_find(bss, linkid + ETH_ALEN);
  31. if (init == NULL)
  32. return NULL;
  33. resp = sta_find(bss, linkid + 2 * ETH_ALEN);
  34. if (resp == NULL)
  35. return NULL;
  36. dl_list_for_each(tdls, &bss->tdls, struct wlantest_tdls, list) {
  37. if (tdls->init == init && tdls->resp == resp)
  38. return tdls;
  39. }
  40. tdls = os_zalloc(sizeof(*tdls));
  41. if (tdls == NULL)
  42. return NULL;
  43. tdls->init = init;
  44. tdls->resp = resp;
  45. dl_list_add(&bss->tdls, &tdls->list);
  46. return tdls;
  47. }
  48. static int tdls_derive_tpk(struct wlantest_tdls *tdls, const u8 *bssid,
  49. const u8 *ftie, u8 ftie_len)
  50. {
  51. const struct rsn_ftie *f;
  52. u8 key_input[SHA256_MAC_LEN];
  53. const u8 *nonce[2];
  54. size_t len[2];
  55. u8 data[3 * ETH_ALEN];
  56. if (ftie == NULL || ftie_len < sizeof(struct rsn_ftie))
  57. return 0;
  58. f = (const struct rsn_ftie *) ftie;
  59. wpa_hexdump(MSG_DEBUG, "TDLS ANonce", f->anonce, WPA_NONCE_LEN);
  60. wpa_hexdump(MSG_DEBUG, "TDLS SNonce", f->snonce, WPA_NONCE_LEN);
  61. /*
  62. * IEEE Std 802.11z-2010 8.5.9.1:
  63. * TPK-Key-Input = SHA-256(min(SNonce, ANonce) || max(SNonce, ANonce))
  64. */
  65. len[0] = WPA_NONCE_LEN;
  66. len[1] = WPA_NONCE_LEN;
  67. if (os_memcmp(f->anonce, f->snonce, WPA_NONCE_LEN) < 0) {
  68. nonce[0] = f->anonce;
  69. nonce[1] = f->snonce;
  70. } else {
  71. nonce[0] = f->snonce;
  72. nonce[1] = f->anonce;
  73. }
  74. sha256_vector(2, nonce, len, key_input);
  75. wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-Key-Input",
  76. key_input, SHA256_MAC_LEN);
  77. /*
  78. * TPK-Key-Data = KDF-N_KEY(TPK-Key-Input, "TDLS PMK",
  79. * min(MAC_I, MAC_R) || max(MAC_I, MAC_R) || BSSID || N_KEY)
  80. * TODO: is N_KEY really included in KDF Context and if so, in which
  81. * presentation format (little endian 16-bit?) is it used? It gets
  82. * added by the KDF anyway..
  83. */
  84. if (os_memcmp(tdls->init->addr, tdls->resp->addr, ETH_ALEN) < 0) {
  85. os_memcpy(data, tdls->init->addr, ETH_ALEN);
  86. os_memcpy(data + ETH_ALEN, tdls->resp->addr, ETH_ALEN);
  87. } else {
  88. os_memcpy(data, tdls->resp->addr, ETH_ALEN);
  89. os_memcpy(data + ETH_ALEN, tdls->init->addr, ETH_ALEN);
  90. }
  91. os_memcpy(data + 2 * ETH_ALEN, bssid, ETH_ALEN);
  92. wpa_hexdump(MSG_DEBUG, "TDLS: KDF Context", data, sizeof(data));
  93. sha256_prf(key_input, SHA256_MAC_LEN, "TDLS PMK", data, sizeof(data),
  94. (u8 *) &tdls->tpk, sizeof(tdls->tpk));
  95. wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-KCK",
  96. tdls->tpk.kck, sizeof(tdls->tpk.kck));
  97. wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-TK",
  98. tdls->tpk.tk, sizeof(tdls->tpk.tk));
  99. return 1;
  100. }
  101. static int tdls_verify_mic(struct wlantest_tdls *tdls, u8 trans_seq,
  102. struct ieee802_11_elems *elems)
  103. {
  104. u8 *buf, *pos;
  105. int len;
  106. u8 mic[16];
  107. int ret;
  108. const struct rsn_ftie *rx_ftie;
  109. struct rsn_ftie *tmp_ftie;
  110. if (elems->link_id == NULL || elems->rsn_ie == NULL ||
  111. elems->timeout_int == NULL || elems->ftie == NULL)
  112. return -1;
  113. len = 2 * ETH_ALEN + 1 + 2 + 18 + 2 + elems->rsn_ie_len +
  114. 2 + elems->timeout_int_len + 2 + elems->ftie_len;
  115. buf = os_zalloc(len);
  116. if (buf == NULL)
  117. return -1;
  118. pos = buf;
  119. /* 1) TDLS initiator STA MAC address */
  120. os_memcpy(pos, elems->link_id + ETH_ALEN, ETH_ALEN);
  121. pos += ETH_ALEN;
  122. /* 2) TDLS responder STA MAC address */
  123. os_memcpy(pos, elems->link_id + 2 * ETH_ALEN, ETH_ALEN);
  124. pos += ETH_ALEN;
  125. /* 3) Transaction Sequence number */
  126. *pos++ = trans_seq;
  127. /* 4) Link Identifier IE */
  128. os_memcpy(pos, elems->link_id - 2, 2 + 18);
  129. pos += 2 + 18;
  130. /* 5) RSN IE */
  131. os_memcpy(pos, elems->rsn_ie - 2, 2 + elems->rsn_ie_len);
  132. pos += 2 + elems->rsn_ie_len;
  133. /* 6) Timeout Interval IE */
  134. os_memcpy(pos, elems->timeout_int - 2, 2 + elems->timeout_int_len);
  135. pos += 2 + elems->timeout_int_len;
  136. /* 7) FTIE, with the MIC field of the FTIE set to 0 */
  137. os_memcpy(pos, elems->ftie - 2, 2 + elems->ftie_len);
  138. pos += 2;
  139. tmp_ftie = (struct rsn_ftie *) pos;
  140. os_memset(tmp_ftie->mic, 0, 16);
  141. pos += elems->ftie_len;
  142. wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf);
  143. wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", tdls->tpk.kck, 16);
  144. ret = omac1_aes_128(tdls->tpk.kck, buf, pos - buf, mic);
  145. os_free(buf);
  146. if (ret)
  147. return -1;
  148. wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16);
  149. rx_ftie = (const struct rsn_ftie *) elems->ftie;
  150. if (os_memcmp(mic, rx_ftie->mic, 16) == 0) {
  151. wpa_printf(MSG_DEBUG, "TDLS: Valid MIC");
  152. return 0;
  153. }
  154. wpa_printf(MSG_DEBUG, "TDLS: Invalid MIC");
  155. return -1;
  156. }
  157. static void rx_data_tdls_setup_request(struct wlantest *wt, const u8 *bssid,
  158. const u8 *sta_addr, const u8 *dst,
  159. const u8 *src,
  160. const u8 *data, size_t len)
  161. {
  162. struct ieee802_11_elems elems;
  163. if (len < 3)
  164. return;
  165. wpa_printf(MSG_DEBUG, "TDLS Setup Request " MACSTR " -> "
  166. MACSTR, MAC2STR(src), MAC2STR(dst));
  167. if (ieee802_11_parse_elems(data + 3, len - 3, &elems, 1) ==
  168. ParseFailed || elems.link_id == NULL)
  169. return;
  170. wpa_printf(MSG_DEBUG, "TDLS Link Identifier: BSSID " MACSTR
  171. " initiator STA " MACSTR " responder STA " MACSTR,
  172. MAC2STR(elems.link_id), MAC2STR(elems.link_id + ETH_ALEN),
  173. MAC2STR(elems.link_id + 2 * ETH_ALEN));
  174. }
  175. static void rx_data_tdls_setup_response(struct wlantest *wt, const u8 *bssid,
  176. const u8 *sta_addr, const u8 *dst,
  177. const u8 *src,
  178. const u8 *data, size_t len)
  179. {
  180. u16 status;
  181. struct ieee802_11_elems elems;
  182. struct wlantest_tdls *tdls;
  183. if (len < 5)
  184. return;
  185. status = WPA_GET_LE16(data);
  186. wpa_printf(MSG_DEBUG, "TDLS Setup Response " MACSTR " -> "
  187. MACSTR " (status %d)",
  188. MAC2STR(src), MAC2STR(dst), status);
  189. if (status != WLAN_STATUS_SUCCESS)
  190. return;
  191. if (ieee802_11_parse_elems(data + 5, len - 5, &elems, 1) ==
  192. ParseFailed || elems.link_id == NULL)
  193. return;
  194. wpa_printf(MSG_DEBUG, "TDLS Link Identifier: BSSID " MACSTR
  195. " initiator STA " MACSTR " responder STA " MACSTR,
  196. MAC2STR(elems.link_id), MAC2STR(elems.link_id + ETH_ALEN),
  197. MAC2STR(elems.link_id + 2 * ETH_ALEN));
  198. tdls = get_tdls(wt, elems.link_id);
  199. if (!tdls)
  200. return;
  201. if (tdls_derive_tpk(tdls, bssid, elems.ftie, elems.ftie_len) < 1)
  202. return;
  203. if (tdls_verify_mic(tdls, 2, &elems) == 0) {
  204. tdls->dialog_token = data[2];
  205. wpa_printf(MSG_DEBUG, "TDLS: Dialog Token for the link: %u",
  206. tdls->dialog_token);
  207. }
  208. }
  209. static void rx_data_tdls_setup_confirm(struct wlantest *wt, const u8 *bssid,
  210. const u8 *sta_addr, const u8 *dst,
  211. const u8 *src,
  212. const u8 *data, size_t len)
  213. {
  214. u16 status;
  215. struct ieee802_11_elems elems;
  216. struct wlantest_tdls *tdls;
  217. if (len < 3)
  218. return;
  219. status = WPA_GET_LE16(data);
  220. wpa_printf(MSG_DEBUG, "TDLS Setup Confirm " MACSTR " -> "
  221. MACSTR " (status %d)",
  222. MAC2STR(src), MAC2STR(dst), status);
  223. if (status != WLAN_STATUS_SUCCESS)
  224. return;
  225. if (ieee802_11_parse_elems(data + 3, len - 3, &elems, 1) ==
  226. ParseFailed || elems.link_id == NULL)
  227. return;
  228. wpa_printf(MSG_DEBUG, "TDLS Link Identifier: BSSID " MACSTR
  229. " initiator STA " MACSTR " responder STA " MACSTR,
  230. MAC2STR(elems.link_id), MAC2STR(elems.link_id + ETH_ALEN),
  231. MAC2STR(elems.link_id + 2 * ETH_ALEN));
  232. tdls = get_tdls(wt, elems.link_id);
  233. if (tdls == NULL)
  234. return;
  235. tdls->link_up = 1;
  236. if (tdls_derive_tpk(tdls, bssid, elems.ftie, elems.ftie_len) < 1)
  237. return;
  238. if (tdls_verify_mic(tdls, 3, &elems) == 0) {
  239. tdls->dialog_token = data[2];
  240. wpa_printf(MSG_DEBUG, "TDLS: Dialog Token for the link: %u",
  241. tdls->dialog_token);
  242. }
  243. }
  244. static int tdls_verify_mic_teardown(struct wlantest_tdls *tdls, u8 trans_seq,
  245. const u8 *reason_code,
  246. struct ieee802_11_elems *elems)
  247. {
  248. u8 *buf, *pos;
  249. int len;
  250. u8 mic[16];
  251. int ret;
  252. const struct rsn_ftie *rx_ftie;
  253. struct rsn_ftie *tmp_ftie;
  254. if (elems->link_id == NULL || elems->ftie == NULL)
  255. return -1;
  256. len = 2 + 18 + 2 + 1 + 1 + 2 + elems->ftie_len;
  257. buf = os_zalloc(len);
  258. if (buf == NULL)
  259. return -1;
  260. pos = buf;
  261. /* 1) Link Identifier IE */
  262. os_memcpy(pos, elems->link_id - 2, 2 + 18);
  263. pos += 2 + 18;
  264. /* 2) Reason Code */
  265. os_memcpy(pos, reason_code, 2);
  266. pos += 2;
  267. /* 3) Dialog token */
  268. *pos++ = tdls->dialog_token;
  269. /* 4) Transaction Sequence number */
  270. *pos++ = trans_seq;
  271. /* 5) FTIE, with the MIC field of the FTIE set to 0 */
  272. os_memcpy(pos, elems->ftie - 2, 2 + elems->ftie_len);
  273. pos += 2;
  274. tmp_ftie = (struct rsn_ftie *) pos;
  275. os_memset(tmp_ftie->mic, 0, 16);
  276. pos += elems->ftie_len;
  277. wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf);
  278. wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", tdls->tpk.kck, 16);
  279. ret = omac1_aes_128(tdls->tpk.kck, buf, pos - buf, mic);
  280. os_free(buf);
  281. if (ret)
  282. return -1;
  283. wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16);
  284. rx_ftie = (const struct rsn_ftie *) elems->ftie;
  285. if (os_memcmp(mic, rx_ftie->mic, 16) == 0) {
  286. wpa_printf(MSG_DEBUG, "TDLS: Valid MIC");
  287. return 0;
  288. }
  289. wpa_printf(MSG_DEBUG, "TDLS: Invalid MIC");
  290. return -1;
  291. }
  292. static void rx_data_tdls_teardown(struct wlantest *wt, const u8 *bssid,
  293. const u8 *sta_addr, const u8 *dst,
  294. const u8 *src,
  295. const u8 *data, size_t len)
  296. {
  297. u16 reason;
  298. struct ieee802_11_elems elems;
  299. struct wlantest_tdls *tdls;
  300. if (len < 2)
  301. return;
  302. reason = WPA_GET_LE16(data);
  303. wpa_printf(MSG_DEBUG, "TDLS Teardown " MACSTR " -> "
  304. MACSTR " (reason %d)",
  305. MAC2STR(src), MAC2STR(dst), reason);
  306. if (ieee802_11_parse_elems(data + 2, len - 2, &elems, 1) ==
  307. ParseFailed || elems.link_id == NULL)
  308. return;
  309. wpa_printf(MSG_DEBUG, "TDLS Link Identifier: BSSID " MACSTR
  310. " initiator STA " MACSTR " responder STA " MACSTR,
  311. MAC2STR(elems.link_id), MAC2STR(elems.link_id + ETH_ALEN),
  312. MAC2STR(elems.link_id + 2 * ETH_ALEN));
  313. tdls = get_tdls(wt, elems.link_id);
  314. if (tdls) {
  315. tdls->link_up = 0;
  316. tdls_verify_mic_teardown(tdls, 4, data, &elems);
  317. }
  318. }
  319. static void rx_data_tdls(struct wlantest *wt, const u8 *bssid,
  320. const u8 *sta_addr, const u8 *dst, const u8 *src,
  321. const u8 *data, size_t len)
  322. {
  323. /* data contains the payload of a TDLS Action frame */
  324. if (len < 2 || data[0] != WLAN_ACTION_TDLS) {
  325. wpa_hexdump(MSG_DEBUG, "Unrecognized encapsulated TDLS frame",
  326. data, len);
  327. return;
  328. }
  329. switch (data[1]) {
  330. case WLAN_TDLS_SETUP_REQUEST:
  331. rx_data_tdls_setup_request(wt, bssid, sta_addr, dst, src,
  332. data + 2, len - 2);
  333. break;
  334. case WLAN_TDLS_SETUP_RESPONSE:
  335. rx_data_tdls_setup_response(wt, bssid, sta_addr, dst, src,
  336. data + 2, len - 2);
  337. break;
  338. case WLAN_TDLS_SETUP_CONFIRM:
  339. rx_data_tdls_setup_confirm(wt, bssid, sta_addr, dst, src,
  340. data + 2, len - 2);
  341. break;
  342. case WLAN_TDLS_TEARDOWN:
  343. rx_data_tdls_teardown(wt, bssid, sta_addr, dst, src, data + 2,
  344. len - 2);
  345. break;
  346. case WLAN_TDLS_DISCOVERY_REQUEST:
  347. wpa_printf(MSG_DEBUG, "TDLS Discovery Request " MACSTR " -> "
  348. MACSTR, MAC2STR(src), MAC2STR(dst));
  349. break;
  350. }
  351. }
  352. void rx_data_80211_encap(struct wlantest *wt, const u8 *bssid,
  353. const u8 *sta_addr, const u8 *dst, const u8 *src,
  354. const u8 *data, size_t len)
  355. {
  356. wpa_hexdump(MSG_EXCESSIVE, "802.11 data encap frame", data, len);
  357. if (len < 1)
  358. return;
  359. if (data[0] == 0x02)
  360. rx_data_tdls(wt, bssid, sta_addr, dst, src, data + 1, len - 1);
  361. }