rx_tdls.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  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)
  234. tdls->link_up = 1;
  235. if (tdls_derive_tpk(tdls, bssid, elems.ftie, elems.ftie_len) < 1)
  236. return;
  237. if (tdls_verify_mic(tdls, 3, &elems) == 0) {
  238. tdls->dialog_token = data[2];
  239. wpa_printf(MSG_DEBUG, "TDLS: Dialog Token for the link: %u",
  240. tdls->dialog_token);
  241. }
  242. }
  243. static int tdls_verify_mic_teardown(struct wlantest_tdls *tdls, u8 trans_seq,
  244. const u8 *reason_code,
  245. struct ieee802_11_elems *elems)
  246. {
  247. u8 *buf, *pos;
  248. int len;
  249. u8 mic[16];
  250. int ret;
  251. const struct rsn_ftie *rx_ftie;
  252. struct rsn_ftie *tmp_ftie;
  253. if (elems->link_id == NULL || elems->ftie == NULL)
  254. return -1;
  255. len = 2 + 18 + 2 + 1 + 1 + 2 + elems->ftie_len;
  256. buf = os_zalloc(len);
  257. if (buf == NULL)
  258. return -1;
  259. pos = buf;
  260. /* 1) Link Identifier IE */
  261. os_memcpy(pos, elems->link_id - 2, 2 + 18);
  262. pos += 2 + 18;
  263. /* 2) Reason Code */
  264. os_memcpy(pos, reason_code, 2);
  265. pos += 2;
  266. /* 3) Dialog token */
  267. *pos++ = tdls->dialog_token;
  268. /* 4) Transaction Sequence number */
  269. *pos++ = trans_seq;
  270. /* 5) FTIE, with the MIC field of the FTIE set to 0 */
  271. os_memcpy(pos, elems->ftie - 2, 2 + elems->ftie_len);
  272. pos += 2;
  273. tmp_ftie = (struct rsn_ftie *) pos;
  274. os_memset(tmp_ftie->mic, 0, 16);
  275. pos += elems->ftie_len;
  276. wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf);
  277. wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", tdls->tpk.kck, 16);
  278. ret = omac1_aes_128(tdls->tpk.kck, buf, pos - buf, mic);
  279. os_free(buf);
  280. if (ret)
  281. return -1;
  282. wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16);
  283. rx_ftie = (const struct rsn_ftie *) elems->ftie;
  284. if (os_memcmp(mic, rx_ftie->mic, 16) == 0) {
  285. wpa_printf(MSG_DEBUG, "TDLS: Valid MIC");
  286. return 0;
  287. }
  288. wpa_printf(MSG_DEBUG, "TDLS: Invalid MIC");
  289. return -1;
  290. }
  291. static void rx_data_tdls_teardown(struct wlantest *wt, const u8 *bssid,
  292. const u8 *sta_addr, const u8 *dst,
  293. const u8 *src,
  294. const u8 *data, size_t len)
  295. {
  296. u16 reason;
  297. struct ieee802_11_elems elems;
  298. struct wlantest_tdls *tdls;
  299. if (len < 2)
  300. return;
  301. reason = WPA_GET_LE16(data);
  302. wpa_printf(MSG_DEBUG, "TDLS Teardown " MACSTR " -> "
  303. MACSTR " (reason %d)",
  304. MAC2STR(src), MAC2STR(dst), reason);
  305. if (ieee802_11_parse_elems(data + 2, len - 2, &elems, 1) ==
  306. ParseFailed || elems.link_id == NULL)
  307. return;
  308. wpa_printf(MSG_DEBUG, "TDLS Link Identifier: BSSID " MACSTR
  309. " initiator STA " MACSTR " responder STA " MACSTR,
  310. MAC2STR(elems.link_id), MAC2STR(elems.link_id + ETH_ALEN),
  311. MAC2STR(elems.link_id + 2 * ETH_ALEN));
  312. tdls = get_tdls(wt, elems.link_id);
  313. if (tdls)
  314. tdls->link_up = 0;
  315. tdls_verify_mic_teardown(tdls, 4, data, &elems);
  316. }
  317. static void rx_data_tdls(struct wlantest *wt, const u8 *bssid,
  318. const u8 *sta_addr, const u8 *dst, const u8 *src,
  319. const u8 *data, size_t len)
  320. {
  321. /* data contains the payload of a TDLS Action frame */
  322. if (len < 2 || data[0] != WLAN_ACTION_TDLS) {
  323. wpa_hexdump(MSG_DEBUG, "Unrecognized encapsulated TDLS frame",
  324. data, len);
  325. return;
  326. }
  327. switch (data[1]) {
  328. case WLAN_TDLS_SETUP_REQUEST:
  329. rx_data_tdls_setup_request(wt, bssid, sta_addr, dst, src,
  330. data + 2, len - 2);
  331. break;
  332. case WLAN_TDLS_SETUP_RESPONSE:
  333. rx_data_tdls_setup_response(wt, bssid, sta_addr, dst, src,
  334. data + 2, len - 2);
  335. break;
  336. case WLAN_TDLS_SETUP_CONFIRM:
  337. rx_data_tdls_setup_confirm(wt, bssid, sta_addr, dst, src,
  338. data + 2, len - 2);
  339. break;
  340. case WLAN_TDLS_TEARDOWN:
  341. rx_data_tdls_teardown(wt, bssid, sta_addr, dst, src, data + 2,
  342. len - 2);
  343. break;
  344. case WLAN_TDLS_DISCOVERY_REQUEST:
  345. wpa_printf(MSG_DEBUG, "TDLS Discovery Request " MACSTR " -> "
  346. MACSTR, MAC2STR(src), MAC2STR(dst));
  347. break;
  348. }
  349. }
  350. void rx_data_80211_encap(struct wlantest *wt, const u8 *bssid,
  351. const u8 *sta_addr, const u8 *dst, const u8 *src,
  352. const u8 *data, size_t len)
  353. {
  354. wpa_hexdump(MSG_EXCESSIVE, "802.11 data encap frame", data, len);
  355. if (len < 1)
  356. return;
  357. if (data[0] == 0x02)
  358. rx_data_tdls(wt, bssid, sta_addr, dst, src, data + 1, len - 1);
  359. }