peerkey_auth.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. /*
  2. * hostapd - PeerKey for Direct Link Setup (DLS)
  3. * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
  4. *
  5. * This software may be distributed under the terms of the BSD license.
  6. * See README for more details.
  7. */
  8. #include "utils/includes.h"
  9. #include "utils/common.h"
  10. #include "utils/eloop.h"
  11. #include "crypto/sha1.h"
  12. #include "crypto/sha256.h"
  13. #include "crypto/random.h"
  14. #include "wpa_auth.h"
  15. #include "wpa_auth_i.h"
  16. #include "wpa_auth_ie.h"
  17. #ifdef CONFIG_PEERKEY
  18. static void wpa_stsl_step(void *eloop_ctx, void *timeout_ctx)
  19. {
  20. #if 0
  21. struct wpa_authenticator *wpa_auth = eloop_ctx;
  22. struct wpa_stsl_negotiation *neg = timeout_ctx;
  23. #endif
  24. /* TODO: ? */
  25. }
  26. struct wpa_stsl_search {
  27. const u8 *addr;
  28. struct wpa_state_machine *sm;
  29. };
  30. static int wpa_stsl_select_sta(struct wpa_state_machine *sm, void *ctx)
  31. {
  32. struct wpa_stsl_search *search = ctx;
  33. if (os_memcmp(search->addr, sm->addr, ETH_ALEN) == 0) {
  34. search->sm = sm;
  35. return 1;
  36. }
  37. return 0;
  38. }
  39. static void wpa_smk_send_error(struct wpa_authenticator *wpa_auth,
  40. struct wpa_state_machine *sm, const u8 *peer,
  41. u16 mui, u16 error_type)
  42. {
  43. u8 kde[2 + RSN_SELECTOR_LEN + ETH_ALEN +
  44. 2 + RSN_SELECTOR_LEN + sizeof(struct rsn_error_kde)];
  45. u8 *pos;
  46. struct rsn_error_kde error;
  47. wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
  48. "Sending SMK Error");
  49. pos = kde;
  50. if (peer) {
  51. pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN,
  52. NULL, 0);
  53. }
  54. error.mui = host_to_be16(mui);
  55. error.error_type = host_to_be16(error_type);
  56. pos = wpa_add_kde(pos, RSN_KEY_DATA_ERROR,
  57. (u8 *) &error, sizeof(error), NULL, 0);
  58. __wpa_send_eapol(wpa_auth, sm,
  59. WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
  60. WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_ERROR,
  61. NULL, NULL, kde, pos - kde, 0, 0, 0);
  62. }
  63. void wpa_smk_m1(struct wpa_authenticator *wpa_auth,
  64. struct wpa_state_machine *sm, struct wpa_eapol_key *key,
  65. const u8 *key_data, size_t key_data_len)
  66. {
  67. struct wpa_eapol_ie_parse kde;
  68. struct wpa_stsl_search search;
  69. u8 *buf, *pos;
  70. size_t buf_len;
  71. if (wpa_parse_kde_ies(key_data, key_data_len, &kde) < 0) {
  72. wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M1");
  73. return;
  74. }
  75. if (kde.rsn_ie == NULL || kde.mac_addr == NULL ||
  76. kde.mac_addr_len < ETH_ALEN) {
  77. wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in "
  78. "SMK M1");
  79. return;
  80. }
  81. /* Initiator = sm->addr; Peer = kde.mac_addr */
  82. search.addr = kde.mac_addr;
  83. search.sm = NULL;
  84. if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
  85. 0 || search.sm == NULL) {
  86. wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR
  87. " aborted - STA not associated anymore",
  88. MAC2STR(kde.mac_addr));
  89. wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK,
  90. STK_ERR_STA_NR);
  91. /* FIX: wpa_stsl_remove(wpa_auth, neg); */
  92. return;
  93. }
  94. buf_len = kde.rsn_ie_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN;
  95. buf = os_malloc(buf_len);
  96. if (buf == NULL)
  97. return;
  98. /* Initiator RSN IE */
  99. os_memcpy(buf, kde.rsn_ie, kde.rsn_ie_len);
  100. pos = buf + kde.rsn_ie_len;
  101. /* Initiator MAC Address */
  102. pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, sm->addr, ETH_ALEN,
  103. NULL, 0);
  104. /* SMK M2:
  105. * EAPOL-Key(S=1, M=1, A=1, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
  106. * MIC=MIC, DataKDs=(RSNIE_I, MAC_I KDE)
  107. */
  108. wpa_auth_logger(wpa_auth, search.sm->addr, LOGGER_DEBUG,
  109. "Sending SMK M2");
  110. __wpa_send_eapol(wpa_auth, search.sm,
  111. WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
  112. WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE,
  113. NULL, key->key_nonce, buf, pos - buf, 0, 0, 0);
  114. os_free(buf);
  115. }
  116. static void wpa_send_smk_m4(struct wpa_authenticator *wpa_auth,
  117. struct wpa_state_machine *sm,
  118. struct wpa_eapol_key *key,
  119. struct wpa_eapol_ie_parse *kde,
  120. const u8 *smk)
  121. {
  122. u8 *buf, *pos;
  123. size_t buf_len;
  124. u32 lifetime;
  125. /* SMK M4:
  126. * EAPOL-Key(S=1, M=1, A=0, I=1, K=0, SM=1, KeyRSC=0, Nonce=PNonce,
  127. * MIC=MIC, DataKDs=(MAC_I KDE, INonce KDE, SMK KDE,
  128. * Lifetime KDE)
  129. */
  130. buf_len = 2 + RSN_SELECTOR_LEN + ETH_ALEN +
  131. 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN +
  132. 2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN +
  133. 2 + RSN_SELECTOR_LEN + sizeof(lifetime);
  134. pos = buf = os_malloc(buf_len);
  135. if (buf == NULL)
  136. return;
  137. /* Initiator MAC Address */
  138. pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, kde->mac_addr, ETH_ALEN,
  139. NULL, 0);
  140. /* Initiator Nonce */
  141. pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, kde->nonce, WPA_NONCE_LEN,
  142. NULL, 0);
  143. /* SMK with PNonce */
  144. pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN,
  145. key->key_nonce, WPA_NONCE_LEN);
  146. /* Lifetime */
  147. lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */
  148. pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
  149. (u8 *) &lifetime, sizeof(lifetime), NULL, 0);
  150. wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
  151. "Sending SMK M4");
  152. __wpa_send_eapol(wpa_auth, sm,
  153. WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
  154. WPA_KEY_INFO_INSTALL | WPA_KEY_INFO_SMK_MESSAGE,
  155. NULL, key->key_nonce, buf, pos - buf, 0, 1, 0);
  156. os_free(buf);
  157. }
  158. static void wpa_send_smk_m5(struct wpa_authenticator *wpa_auth,
  159. struct wpa_state_machine *sm,
  160. struct wpa_eapol_key *key,
  161. struct wpa_eapol_ie_parse *kde,
  162. const u8 *smk, const u8 *peer)
  163. {
  164. u8 *buf, *pos;
  165. size_t buf_len;
  166. u32 lifetime;
  167. /* SMK M5:
  168. * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
  169. * MIC=MIC, DataKDs=(RSNIE_P, MAC_P KDE, PNonce, SMK KDE,
  170. * Lifetime KDE))
  171. */
  172. buf_len = kde->rsn_ie_len +
  173. 2 + RSN_SELECTOR_LEN + ETH_ALEN +
  174. 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN +
  175. 2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN +
  176. 2 + RSN_SELECTOR_LEN + sizeof(lifetime);
  177. pos = buf = os_malloc(buf_len);
  178. if (buf == NULL)
  179. return;
  180. /* Peer RSN IE */
  181. os_memcpy(pos, kde->rsn_ie, kde->rsn_ie_len);
  182. pos += kde->rsn_ie_len;
  183. /* Peer MAC Address */
  184. pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN, NULL, 0);
  185. /* PNonce */
  186. pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, key->key_nonce,
  187. WPA_NONCE_LEN, NULL, 0);
  188. /* SMK and INonce */
  189. pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN,
  190. kde->nonce, WPA_NONCE_LEN);
  191. /* Lifetime */
  192. lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */
  193. pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
  194. (u8 *) &lifetime, sizeof(lifetime), NULL, 0);
  195. wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
  196. "Sending SMK M5");
  197. __wpa_send_eapol(wpa_auth, sm,
  198. WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
  199. WPA_KEY_INFO_SMK_MESSAGE,
  200. NULL, kde->nonce, buf, pos - buf, 0, 1, 0);
  201. os_free(buf);
  202. }
  203. void wpa_smk_m3(struct wpa_authenticator *wpa_auth,
  204. struct wpa_state_machine *sm, struct wpa_eapol_key *key,
  205. const u8 *key_data, size_t key_data_len)
  206. {
  207. struct wpa_eapol_ie_parse kde;
  208. struct wpa_stsl_search search;
  209. u8 smk[32], buf[ETH_ALEN + 8 + 2 * WPA_NONCE_LEN], *pos;
  210. if (wpa_parse_kde_ies(key_data, key_data_len, &kde) < 0) {
  211. wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M3");
  212. return;
  213. }
  214. if (kde.rsn_ie == NULL ||
  215. kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
  216. kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN) {
  217. wpa_printf(MSG_INFO, "RSN: No RSN IE, MAC address KDE, or "
  218. "Nonce KDE in SMK M3");
  219. return;
  220. }
  221. /* Peer = sm->addr; Initiator = kde.mac_addr;
  222. * Peer Nonce = key->key_nonce; Initiator Nonce = kde.nonce */
  223. search.addr = kde.mac_addr;
  224. search.sm = NULL;
  225. if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
  226. 0 || search.sm == NULL) {
  227. wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR
  228. " aborted - STA not associated anymore",
  229. MAC2STR(kde.mac_addr));
  230. wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK,
  231. STK_ERR_STA_NR);
  232. /* FIX: wpa_stsl_remove(wpa_auth, neg); */
  233. return;
  234. }
  235. if (random_get_bytes(smk, PMK_LEN)) {
  236. wpa_printf(MSG_DEBUG, "RSN: Failed to generate SMK");
  237. return;
  238. }
  239. /* SMK = PRF-256(Random number, "SMK Derivation",
  240. * AA || Time || INonce || PNonce)
  241. */
  242. os_memcpy(buf, wpa_auth->addr, ETH_ALEN);
  243. pos = buf + ETH_ALEN;
  244. wpa_get_ntp_timestamp(pos);
  245. pos += 8;
  246. os_memcpy(pos, kde.nonce, WPA_NONCE_LEN);
  247. pos += WPA_NONCE_LEN;
  248. os_memcpy(pos, key->key_nonce, WPA_NONCE_LEN);
  249. #ifdef CONFIG_IEEE80211W
  250. sha256_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf),
  251. smk, PMK_LEN);
  252. #else /* CONFIG_IEEE80211W */
  253. sha1_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf),
  254. smk, PMK_LEN);
  255. #endif /* CONFIG_IEEE80211W */
  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,
  265. const u8 *key_data, size_t key_data_len)
  266. {
  267. struct wpa_eapol_ie_parse kde;
  268. struct wpa_stsl_search search;
  269. struct rsn_error_kde error;
  270. u16 mui, error_type;
  271. if (wpa_parse_kde_ies(key_data, key_data_len, &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 */