📄 wpa.c
字号:
}SM_STATE(WPA_PTK, PTKCALCNEGOTIATING2){ SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING2, wpa_ptk); sm->TimeoutCtr = 0;}#ifdef CONFIG_IEEE80211Wstatic int ieee80211w_kde_len(struct wpa_state_machine *sm){ if (sm->mgmt_frame_prot) { return 2 + RSN_SELECTOR_LEN + sizeof(struct wpa_igtk_kde); } return 0;}static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos){ struct wpa_igtk_kde igtk; struct wpa_group *gsm = sm->group; if (!sm->mgmt_frame_prot) return pos; igtk.keyid[0] = gsm->GN_igtk; igtk.keyid[1] = 0; if (wpa_auth_get_seqnum_igtk(sm->wpa_auth, NULL, gsm->GN_igtk, igtk.pn) < 0) os_memset(igtk.pn, 0, sizeof(igtk.pn)); os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN); pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK, (const u8 *) &igtk, sizeof(igtk), NULL, 0); return pos;}#else /* CONFIG_IEEE80211W */static int ieee80211w_kde_len(struct wpa_state_machine *sm){ return 0;}static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos){ return pos;}#endif /* CONFIG_IEEE80211W */SM_STATE(WPA_PTK, PTKINITNEGOTIATING){ u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos; size_t gtk_len, kde_len; struct wpa_group *gsm = sm->group; u8 *wpa_ie; int wpa_ie_len, secure, keyidx, encr = 0; SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk); sm->TimeoutEvt = FALSE; sm->TimeoutCtr++; if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) { /* No point in sending the EAPOL-Key - we will disconnect * immediately following this. */ return; } /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, GTK[GN]) */ os_memset(rsc, 0, WPA_KEY_RSC_LEN); wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc); wpa_ie = sm->wpa_auth->wpa_ie; wpa_ie_len = sm->wpa_auth->wpa_ie_len; if (sm->wpa == WPA_VERSION_WPA && (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) && wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) { /* WPA-only STA, remove RSN IE */ wpa_ie = wpa_ie + wpa_ie[1] + 2; wpa_ie_len = wpa_ie[1] + 2; } wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, "sending 3/4 msg of 4-Way Handshake"); if (sm->wpa == WPA_VERSION_WPA2) { /* WPA2 send GTK in the 4-way handshake */ secure = 1; gtk = gsm->GTK[gsm->GN - 1]; gtk_len = gsm->GTK_len; keyidx = gsm->GN; _rsc = rsc; encr = 1; } else { /* WPA does not include GTK in msg 3/4 */ secure = 0; gtk = NULL; gtk_len = 0; keyidx = 0; _rsc = NULL; } kde_len = wpa_ie_len + ieee80211w_kde_len(sm); if (gtk) kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len; kde = os_malloc(kde_len); if (kde == NULL) return; pos = kde; os_memcpy(pos, wpa_ie, wpa_ie_len); pos += wpa_ie_len; if (gtk) { u8 hdr[2]; hdr[0] = keyidx & 0x03; hdr[1] = 0; pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, gtk, gtk_len); } pos = ieee80211w_kde_add(sm, pos); wpa_send_eapol(sm->wpa_auth, sm, (secure ? WPA_KEY_INFO_SECURE : 0) | WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL | WPA_KEY_INFO_KEY_TYPE, _rsc, sm->ANonce, kde, pos - kde, keyidx, encr); os_free(kde);}SM_STATE(WPA_PTK, PTKINITDONE){ SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk); sm->EAPOLKeyReceived = FALSE; if (sm->Pair) { char *alg; int klen; if (sm->pairwise == WPA_CIPHER_TKIP) { alg = "TKIP"; klen = 32; } else { alg = "CCMP"; klen = 16; } if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, sm->PTK.tk1, klen)) { wpa_sta_disconnect(sm->wpa_auth, sm->addr); return; } /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ sm->pairwise_set = TRUE; if (sm->wpa_auth->conf.wpa_ptk_rekey) { eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); eloop_register_timeout(sm->wpa_auth->conf. wpa_ptk_rekey, 0, wpa_rekey_ptk, sm->wpa_auth, sm); } if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_authorized, 1); } } if (0 /* IBSS == TRUE */) { sm->keycount++; if (sm->keycount == 2) { wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 1); } } else { wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 1); } wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyAvailable, 0); wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyDone, 1); if (sm->wpa == WPA_VERSION_WPA) sm->PInitAKeys = TRUE; else sm->has_GTK = TRUE; wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, "pairwise key handshake completed (%s)", sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");#ifdef CONFIG_IEEE80211R wpa_ft_push_pmk_r1(sm->wpa_auth, sm->addr);#endif /* CONFIG_IEEE80211R */}SM_STEP(WPA_PTK){ struct wpa_authenticator *wpa_auth = sm->wpa_auth; if (sm->Init) SM_ENTER(WPA_PTK, INITIALIZE); else if (sm->Disconnect /* || FIX: dot11RSNAConfigSALifetime timeout */) SM_ENTER(WPA_PTK, DISCONNECT); else if (sm->DeauthenticationRequest) SM_ENTER(WPA_PTK, DISCONNECTED); else if (sm->AuthenticationRequest) SM_ENTER(WPA_PTK, AUTHENTICATION); else if (sm->ReAuthenticationRequest) SM_ENTER(WPA_PTK, AUTHENTICATION2); else if (sm->PTKRequest) SM_ENTER(WPA_PTK, PTKSTART); else switch (sm->wpa_ptk_state) { case WPA_PTK_INITIALIZE: break; case WPA_PTK_DISCONNECT: SM_ENTER(WPA_PTK, DISCONNECTED); break; case WPA_PTK_DISCONNECTED: SM_ENTER(WPA_PTK, INITIALIZE); break; case WPA_PTK_AUTHENTICATION: SM_ENTER(WPA_PTK, AUTHENTICATION2); break; case WPA_PTK_AUTHENTICATION2: if (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) && wpa_auth_get_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun) > 0) SM_ENTER(WPA_PTK, INITPMK); else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) /* FIX: && 802.1X::keyRun */) SM_ENTER(WPA_PTK, INITPSK); break; case WPA_PTK_INITPMK: if (wpa_auth_get_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyAvailable) > 0) SM_ENTER(WPA_PTK, PTKSTART); else { wpa_auth->dot11RSNA4WayHandshakeFailures++; SM_ENTER(WPA_PTK, DISCONNECT); } break; case WPA_PTK_INITPSK: if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, NULL)) SM_ENTER(WPA_PTK, PTKSTART); else { wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, "no PSK configured for the STA"); wpa_auth->dot11RSNA4WayHandshakeFailures++; SM_ENTER(WPA_PTK, DISCONNECT); } break; case WPA_PTK_PTKSTART: if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && sm->EAPOLKeyPairwise) SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); else if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) { wpa_auth->dot11RSNA4WayHandshakeFailures++; SM_ENTER(WPA_PTK, DISCONNECT); } else if (sm->TimeoutEvt) SM_ENTER(WPA_PTK, PTKSTART); break; case WPA_PTK_PTKCALCNEGOTIATING: if (sm->MICVerified) SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING2); else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && sm->EAPOLKeyPairwise) SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); else if (sm->TimeoutEvt) SM_ENTER(WPA_PTK, PTKSTART); break; case WPA_PTK_PTKCALCNEGOTIATING2: SM_ENTER(WPA_PTK, PTKINITNEGOTIATING); break; case WPA_PTK_PTKINITNEGOTIATING: if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && sm->EAPOLKeyPairwise && sm->MICVerified) SM_ENTER(WPA_PTK, PTKINITDONE); else if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) { wpa_auth->dot11RSNA4WayHandshakeFailures++; SM_ENTER(WPA_PTK, DISCONNECT); } else if (sm->TimeoutEvt) SM_ENTER(WPA_PTK, PTKINITNEGOTIATING); break; case WPA_PTK_PTKINITDONE: break; }}SM_STATE(WPA_PTK_GROUP, IDLE){ SM_ENTRY_MA(WPA_PTK_GROUP, IDLE, wpa_ptk_group); if (sm->Init) { /* Init flag is not cleared here, so avoid busy * loop by claiming nothing changed. */ sm->changed = FALSE; } sm->GTimeoutCtr = 0;}SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING){ u8 rsc[WPA_KEY_RSC_LEN]; struct wpa_group *gsm = sm->group; u8 *kde, *pos, hdr[2]; size_t kde_len; SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group); sm->GTimeoutCtr++; if (sm->GTimeoutCtr > (int) dot11RSNAConfigGroupUpdateCount) { /* No point in sending the EAPOL-Key - we will disconnect * immediately following this. */ return; } if (sm->wpa == WPA_VERSION_WPA) sm->PInitAKeys = FALSE; sm->TimeoutEvt = FALSE; /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */ os_memset(rsc, 0, WPA_KEY_RSC_LEN); if (gsm->wpa_group_state == WPA_GROUP_SETKEYSDONE) wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc); wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, "sending 1/2 msg of Group Key Handshake"); if (sm->wpa == WPA_VERSION_WPA2) { kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len + ieee80211w_kde_len(sm); kde = os_malloc(kde_len); if (kde == NULL) return; pos = kde; hdr[0] = gsm->GN & 0x03; hdr[1] = 0; pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, gsm->GTK[gsm->GN - 1], gsm->GTK_len); pos = ieee80211w_kde_add(sm, pos); } else { kde = gsm->GTK[gsm->GN - 1]; pos = kde + gsm->GTK_len; } wpa_send_eapol(sm->wpa_auth, sm, WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK | (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0), rsc, gsm->GNonce, kde, pos - kde, gsm->GN, 1); if (sm->wpa == WPA_VERSION_WPA2) os_free(kde);}SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED){ SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group); sm->EAPOLKeyReceived = FALSE; if (sm->GUpdateStationKeys) sm->group->GKeyDoneStations--; sm->GUpdateStationKeys = FALSE; sm->GTimeoutCtr = 0; /* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */ wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, "group key handshake completed (%s)", sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); sm->has_GTK = TRUE;}SM_STATE(WPA_PTK_GROUP, KEYERROR){ SM_ENTRY_MA(WPA_PTK_GROUP, KEYERROR, wpa_ptk_group); if (sm->GUpdateStationKeys) sm->group->GKeyDoneStations--; sm->GUpdateStationKeys = FALSE; sm->Disconnect = TRUE;}SM_STEP(WPA_PTK_GROUP){ if (sm->Init || sm->PtkGroupInit) { SM_ENTER(WPA_PTK_GROUP, IDLE); sm->PtkGroupInit = FALSE; } else switch (sm->wpa_ptk_group_state) { case WPA_PTK_GROUP_IDLE: if (sm->GUpdateStationKeys || (sm->wpa == WPA_VERSION_WPA && sm->PInitAKeys)) SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING); break; case WPA_PTK_GROUP_REKEYNEGOTIATING: if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && !sm->EAPOLKeyPairwise && sm->MICVerified) SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED); else if (sm->GTimeoutCtr > (int) dot11RSNAConfigGroupUpdateCount) SM_ENTER(WPA_PTK_GROUP, KEYERROR); else if (sm->TimeoutEvt) SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING); break; case WPA_PTK_GROUP_KEYERROR: SM_ENTER(WPA_PTK_GROUP, IDLE); break; case WPA_PTK_GROUP_REKEYESTABLISHED: SM_ENTER(WPA_PTK_GROUP, IDLE); break; }}static int wpa_gtk_update(struct wpa_authenticator *wpa_auth, struct wpa_group *group){ int ret = 0; /* FIX: is this the correct way of getting GNonce? */ os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); inc_byte_array(group->Counter, WPA_NONCE_LEN); wpa_gmk_to_gtk(group->GMK, wpa_auth->addr, group->GNonce, group->GTK[group->GN - 1], group->GTK_len);#ifdef CONFIG_IEEE80211W if (wpa_auth->conf.ieee80211w != WPA_NO_IEEE80211W) { if (os_get_random(group->IGTK[group->GN_igtk - 4], WPA_IGTK_LEN) < 0) { wpa_printf(MSG_INFO, "RSN: Failed to get new random " "IGTK"); ret = -1; } wpa_hexdump_key(MSG_DEBUG, "IGTK", group->IGTK[group->GN_igtk - 4], WPA_IGTK_LEN); }#endif /* CONFIG_IEEE80211W */ return ret;}static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth, struct wpa_group *group){ wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " "GTK_INIT (VLAN-ID %d)", group->vlan_id); group->changed = FALSE; /* GInit is not cleared here; avoid loop */ group->wpa_group_state = WPA_GROUP_GTK_INIT; /* GTK[0..N] = 0 */ os_memset(group->GTK, 0, sizeof(group->GTK)); group->GN = 1; group->GM = 2;#ifdef CONFIG_IEEE80211W group->GN_igtk = 4; group->GM_igtk = 5;#endif /* CONFIG_IEEE80211W */ /* GTK[GN] = CalcGTK() */ wpa_gtk_update(wpa_auth, group);}static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx){ if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) { wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, "Not in PTKINITDONE; skip Group Key update"); return 0; } if (sm->GUpdateStationKeys) { /* * This should not really happen, but just in case, make sure * we do not count the same STA twice in GKeyDoneStations. */ wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, "GUpdateStationKeys already set - do not " "increment GKeyDoneStations"); } else { sm->group->GKeyDoneStations++; sm->GUpdateStationKeys = TRUE; } wpa_sm_step(sm); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -