peerkey.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. /*
  2. * hostapd - PeerKey for Direct Link Setup (DLS)
  3. * Copyright (c) 2006-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 "eloop.h"
  17. #include "sha1.h"
  18. #include "sha256.h"
  19. #include "wpa.h"
  20. #include "defs.h"
  21. #include "wpa_auth_i.h"
  22. #include "wpa_auth_ie.h"
  23. #ifdef CONFIG_PEERKEY
  24. static void wpa_stsl_step(void *eloop_ctx, void *timeout_ctx)
  25. {
  26. #if 0
  27. struct wpa_authenticator *wpa_auth = eloop_ctx;
  28. struct wpa_stsl_negotiation *neg = timeout_ctx;
  29. #endif
  30. /* TODO: ? */
  31. }
  32. struct wpa_stsl_search {
  33. const u8 *addr;
  34. struct wpa_state_machine *sm;
  35. };
  36. static int wpa_stsl_select_sta(struct wpa_state_machine *sm, void *ctx)
  37. {
  38. struct wpa_stsl_search *search = ctx;
  39. if (os_memcmp(search->addr, sm->addr, ETH_ALEN) == 0) {
  40. search->sm = sm;
  41. return 1;
  42. }
  43. return 0;
  44. }
  45. static void wpa_smk_send_error(struct wpa_authenticator *wpa_auth,
  46. struct wpa_state_machine *sm, const u8 *peer,
  47. u16 mui, u16 error_type)
  48. {
  49. u8 kde[2 + RSN_SELECTOR_LEN + ETH_ALEN +
  50. 2 + RSN_SELECTOR_LEN + sizeof(struct rsn_error_kde)];
  51. u8 *pos;
  52. struct rsn_error_kde error;
  53. wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
  54. "Sending SMK Error");
  55. pos = kde;
  56. if (peer) {
  57. pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN,
  58. NULL, 0);
  59. }
  60. error.mui = host_to_be16(mui);
  61. error.error_type = host_to_be16(error_type);
  62. pos = wpa_add_kde(pos, RSN_KEY_DATA_ERROR,
  63. (u8 *) &error, sizeof(error), NULL, 0);
  64. __wpa_send_eapol(wpa_auth, sm,
  65. WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
  66. WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_ERROR,
  67. NULL, NULL, kde, pos - kde, 0, 0, 0);
  68. }
  69. void wpa_smk_m1(struct wpa_authenticator *wpa_auth,
  70. struct wpa_state_machine *sm, struct wpa_eapol_key *key)
  71. {
  72. struct wpa_eapol_ie_parse kde;
  73. struct wpa_stsl_search search;
  74. u8 *buf, *pos;
  75. size_t buf_len;
  76. if (wpa_parse_kde_ies((const u8 *) (key + 1),
  77. WPA_GET_BE16(key->key_data_length), &kde) < 0) {
  78. wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M1");
  79. return;
  80. }
  81. if (kde.rsn_ie == NULL || kde.mac_addr == NULL ||
  82. kde.mac_addr_len < ETH_ALEN) {
  83. wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in "
  84. "SMK M1");
  85. return;
  86. }
  87. /* Initiator = sm->addr; Peer = kde.mac_addr */
  88. search.addr = kde.mac_addr;
  89. search.sm = NULL;
  90. if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
  91. 0 || search.sm == NULL) {
  92. wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR
  93. " aborted - STA not associated anymore",
  94. MAC2STR(kde.mac_addr));
  95. wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK,
  96. STK_ERR_STA_NR);
  97. /* FIX: wpa_stsl_remove(wpa_auth, neg); */
  98. return;
  99. }
  100. buf_len = kde.rsn_ie_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN;
  101. buf = os_malloc(buf_len);
  102. if (buf == NULL)
  103. return;
  104. /* Initiator RSN IE */
  105. os_memcpy(buf, kde.rsn_ie, kde.rsn_ie_len);
  106. pos = buf + kde.rsn_ie_len;
  107. /* Initiator MAC Address */
  108. pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, sm->addr, ETH_ALEN,
  109. NULL, 0);
  110. /* SMK M2:
  111. * EAPOL-Key(S=1, M=1, A=1, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
  112. * MIC=MIC, DataKDs=(RSNIE_I, MAC_I KDE)
  113. */
  114. wpa_auth_logger(wpa_auth, search.sm->addr, LOGGER_DEBUG,
  115. "Sending SMK M2");
  116. __wpa_send_eapol(wpa_auth, search.sm,
  117. WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
  118. WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE,
  119. NULL, key->key_nonce, buf, pos - buf, 0, 0, 0);
  120. os_free(buf);
  121. }
  122. static void wpa_send_smk_m4(struct wpa_authenticator *wpa_auth,
  123. struct wpa_state_machine *sm,
  124. struct wpa_eapol_key *key,
  125. struct wpa_eapol_ie_parse *kde,
  126. const u8 *smk)
  127. {
  128. u8 *buf, *pos;
  129. size_t buf_len;
  130. u32 lifetime;
  131. /* SMK M4:
  132. * EAPOL-Key(S=1, M=1, A=0, I=1, K=0, SM=1, KeyRSC=0, Nonce=PNonce,
  133. * MIC=MIC, DataKDs=(MAC_I KDE, INonce KDE, SMK KDE,
  134. * Lifetime KDE)
  135. */
  136. buf_len = 2 + RSN_SELECTOR_LEN + ETH_ALEN +
  137. 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN +
  138. 2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN +
  139. 2 + RSN_SELECTOR_LEN + sizeof(lifetime);
  140. pos = buf = os_malloc(buf_len);
  141. if (buf == NULL)
  142. return;
  143. /* Initiator MAC Address */
  144. pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, kde->mac_addr, ETH_ALEN,
  145. NULL, 0);
  146. /* Initiator Nonce */
  147. pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, kde->nonce, WPA_NONCE_LEN,
  148. NULL, 0);
  149. /* SMK with PNonce */
  150. pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN,
  151. key->key_nonce, WPA_NONCE_LEN);
  152. /* Lifetime */
  153. lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */
  154. pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
  155. (u8 *) &lifetime, sizeof(lifetime), NULL, 0);
  156. wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
  157. "Sending SMK M4");
  158. __wpa_send_eapol(wpa_auth, sm,
  159. WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
  160. WPA_KEY_INFO_INSTALL | WPA_KEY_INFO_SMK_MESSAGE,
  161. NULL, key->key_nonce, buf, pos - buf, 0, 1, 0);
  162. os_free(buf);
  163. }
  164. static void wpa_send_smk_m5(struct wpa_authenticator *wpa_auth,
  165. struct wpa_state_machine *sm,
  166. struct wpa_eapol_key *key,
  167. struct wpa_eapol_ie_parse *kde,
  168. const u8 *smk, const u8 *peer)
  169. {
  170. u8 *buf, *pos;
  171. size_t buf_len;
  172. u32 lifetime;
  173. /* SMK M5:
  174. * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
  175. * MIC=MIC, DataKDs=(RSNIE_P, MAC_P KDE, PNonce, SMK KDE,
  176. * Lifetime KDE))
  177. */
  178. buf_len = kde->rsn_ie_len +
  179. 2 + RSN_SELECTOR_LEN + ETH_ALEN +
  180. 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN +
  181. 2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN +
  182. 2 + RSN_SELECTOR_LEN + sizeof(lifetime);
  183. pos = buf = os_malloc(buf_len);
  184. if (buf == NULL)
  185. return;
  186. /* Peer RSN IE */
  187. os_memcpy(buf, kde->rsn_ie, kde->rsn_ie_len);
  188. pos = buf + kde->rsn_ie_len;
  189. /* Peer MAC Address */
  190. pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN, NULL, 0);
  191. /* PNonce */
  192. pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, key->key_nonce,
  193. WPA_NONCE_LEN, NULL, 0);
  194. /* SMK and INonce */
  195. pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN,
  196. kde->nonce, WPA_NONCE_LEN);
  197. /* Lifetime */
  198. lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */
  199. pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
  200. (u8 *) &lifetime, sizeof(lifetime), NULL, 0);
  201. wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
  202. "Sending SMK M5");
  203. __wpa_send_eapol(wpa_auth, sm,
  204. WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
  205. WPA_KEY_INFO_SMK_MESSAGE,
  206. NULL, kde->nonce, buf, pos - buf, 0, 1, 0);
  207. os_free(buf);
  208. }
  209. void wpa_smk_m3(struct wpa_authenticator *wpa_auth,
  210. struct wpa_state_machine *sm, struct wpa_eapol_key *key)
  211. {
  212. struct wpa_eapol_ie_parse kde;
  213. struct wpa_stsl_search search;
  214. u8 smk[32], buf[ETH_ALEN + 8 + 2 * WPA_NONCE_LEN], *pos;
  215. if (wpa_parse_kde_ies((const u8 *) (key + 1),
  216. WPA_GET_BE16(key->key_data_length), &kde) < 0) {
  217. wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M3");
  218. return;
  219. }
  220. if (kde.rsn_ie == NULL ||
  221. kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
  222. kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN) {
  223. wpa_printf(MSG_INFO, "RSN: No RSN IE, MAC address KDE, or "
  224. "Nonce KDE in SMK M3");
  225. return;
  226. }
  227. /* Peer = sm->addr; Initiator = kde.mac_addr;
  228. * Peer Nonce = key->key_nonce; Initiator Nonce = kde.nonce */
  229. search.addr = kde.mac_addr;
  230. search.sm = NULL;
  231. if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
  232. 0 || search.sm == NULL) {
  233. wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR
  234. " aborted - STA not associated anymore",
  235. MAC2STR(kde.mac_addr));
  236. wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK,
  237. STK_ERR_STA_NR);
  238. /* FIX: wpa_stsl_remove(wpa_auth, neg); */
  239. return;
  240. }
  241. if (os_get_random(smk, PMK_LEN)) {
  242. wpa_printf(MSG_DEBUG, "RSN: Failed to generate SMK");
  243. return;
  244. }
  245. /* SMK = PRF-256(Random number, "SMK Derivation",
  246. * AA || Time || INonce || PNonce)
  247. */
  248. os_memcpy(buf, wpa_auth->addr, ETH_ALEN);
  249. pos = buf + ETH_ALEN;
  250. wpa_get_ntp_timestamp(pos);
  251. pos += 8;
  252. os_memcpy(pos, kde.nonce, WPA_NONCE_LEN);
  253. pos += WPA_NONCE_LEN;
  254. os_memcpy(pos, key->key_nonce, WPA_NONCE_LEN);
  255. #ifdef CONFIG_IEEE80211W
  256. sha256_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf),
  257. smk, PMK_LEN);
  258. #else /* CONFIG_IEEE80211W */
  259. sha1_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf),
  260. smk, PMK_LEN);
  261. #endif /* CONFIG_IEEE80211W */
  262. wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", smk, PMK_LEN);
  263. wpa_send_smk_m4(wpa_auth, sm, key, &kde, smk);
  264. wpa_send_smk_m5(wpa_auth, search.sm, key, &kde, smk, sm->addr);
  265. /* Authenticator does not need SMK anymore and it is required to forget
  266. * it. */
  267. os_memset(smk, 0, sizeof(*smk));
  268. }
  269. void wpa_smk_error(struct wpa_authenticator *wpa_auth,
  270. struct wpa_state_machine *sm, struct wpa_eapol_key *key)
  271. {
  272. struct wpa_eapol_ie_parse kde;
  273. struct wpa_stsl_search search;
  274. struct rsn_error_kde error;
  275. u16 mui, error_type;
  276. if (wpa_parse_kde_ies((const u8 *) (key + 1),
  277. WPA_GET_BE16(key->key_data_length), &kde) < 0) {
  278. wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error");
  279. return;
  280. }
  281. if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
  282. kde.error == NULL || kde.error_len < sizeof(error)) {
  283. wpa_printf(MSG_INFO, "RSN: No MAC address or Error KDE in "
  284. "SMK Error");
  285. return;
  286. }
  287. search.addr = kde.mac_addr;
  288. search.sm = NULL;
  289. if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
  290. 0 || search.sm == NULL) {
  291. wpa_printf(MSG_DEBUG, "RSN: Peer STA " MACSTR " not "
  292. "associated for SMK Error message from " MACSTR,
  293. MAC2STR(kde.mac_addr), MAC2STR(sm->addr));
  294. return;
  295. }
  296. os_memcpy(&error, kde.error, sizeof(error));
  297. mui = be_to_host16(error.mui);
  298. error_type = be_to_host16(error.error_type);
  299. wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
  300. "STA reported SMK Error: Peer " MACSTR
  301. " MUI %d Error Type %d",
  302. MAC2STR(kde.mac_addr), mui, error_type);
  303. wpa_smk_send_error(wpa_auth, search.sm, sm->addr, mui, error_type);
  304. }
  305. int wpa_stsl_remove(struct wpa_authenticator *wpa_auth,
  306. struct wpa_stsl_negotiation *neg)
  307. {
  308. struct wpa_stsl_negotiation *pos, *prev;
  309. if (wpa_auth == NULL)
  310. return -1;
  311. pos = wpa_auth->stsl_negotiations;
  312. prev = NULL;
  313. while (pos) {
  314. if (pos == neg) {
  315. if (prev)
  316. prev->next = pos->next;
  317. else
  318. wpa_auth->stsl_negotiations = pos->next;
  319. eloop_cancel_timeout(wpa_stsl_step, wpa_auth, pos);
  320. os_free(pos);
  321. return 0;
  322. }
  323. prev = pos;
  324. pos = pos->next;
  325. }
  326. return -1;
  327. }
  328. #endif /* CONFIG_PEERKEY */