peerkey.c 10 KB

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