📄 wpa.c
字号:
sm->key_replay_counter, WPA_REPLAY_COUNTER_LEN); hostapd_hexdump("received replay counter", key->replay_counter, WPA_REPLAY_COUNTER_LEN); } return; } switch (msg) { case PAIRWISE_2: if (sm->wpa_ptk_state != WPA_PTK_PTKSTART && sm->wpa_ptk_state != WPA_PTK_PTKCALCNEGOTIATING) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, HOSTAPD_LEVEL_INFO, "received EAPOL-Key msg 2/4 in invalid" " state (%d) - dropped", sm->wpa_ptk_state); return; } if (sta->wpa_ie == NULL || sta->wpa_ie_len != key_data_length || memcmp(sta->wpa_ie, key + 1, key_data_length) != 0) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, HOSTAPD_LEVEL_INFO, "WPA IE from (Re)AssocReq did not match" " with msg 2/4"); if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL)) { if (sta->wpa_ie) { hostapd_hexdump("WPA IE in AssocReq", sta->wpa_ie, sta->wpa_ie_len); } hostapd_hexdump("WPA IE in msg 2/4", (u8 *) (key + 1), key_data_length); } /* MLME-DEAUTHENTICATE.request */ wpa_sta_disconnect(hapd, sta); return; } break; case PAIRWISE_4: if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING || !sm->PTK_valid) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, HOSTAPD_LEVEL_INFO, "received EAPOL-Key msg 4/4 in invalid" " state (%d) - dropped", sm->wpa_ptk_state); return; } break; case GROUP_2: if (sm->wpa_ptk_group_state != WPA_PTK_GROUP_REKEYNEGOTIATING || !sm->PTK_valid) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, HOSTAPD_LEVEL_INFO, "received EAPOL-Key msg 2/2 in invalid" " state (%d) - dropped", sm->wpa_ptk_group_state); return; } break; case REQUEST: break; } hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, HOSTAPD_LEVEL_DEBUG, "received EAPOL-Key frame (%s)", msgtxt); if (key_info & WPA_KEY_INFO_ACK) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, HOSTAPD_LEVEL_INFO, "received invalid EAPOL-Key: Key Ack set"); return; } if (!(key_info & WPA_KEY_INFO_MIC)) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, HOSTAPD_LEVEL_INFO, "received invalid EAPOL-Key: Key MIC not set"); return; } sm->MICVerified = FALSE; if (sm->PTK_valid) { if (wpa_verify_key_mic(&sm->PTK, data, data_len)) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, HOSTAPD_LEVEL_INFO, "received EAPOL-Key with invalid MIC"); return; } sm->MICVerified = TRUE; eloop_cancel_timeout(wpa_send_eapol_timeout, sta->wpa_sm->hapd, sta); } if (key_info & WPA_KEY_INFO_REQUEST) { if (sm->MICVerified) { sta->req_replay_counter_used = 1; memcpy(sta->req_replay_counter, key->replay_counter, WPA_REPLAY_COUNTER_LEN); } else { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, HOSTAPD_LEVEL_INFO, "received EAPOL-Key request with " "invalid MIC"); return; } if (key_info & WPA_KEY_INFO_ERROR) { /* Supplicant reported a Michael MIC error */ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, HOSTAPD_LEVEL_INFO, "received EAPOL-Key Error Request " "(STA detected Michael MIC failure)"); ieee80211_michael_mic_failure(hapd, sta->addr, 0); sta->dot11RSNAStatsTKIPRemoteMICFailures++; hapd->wpa_auth->dot11RSNAStatsTKIPRemoteMICFailures++; /* Error report is not a request for a new key * handshake, but since Authenticator may do it, let's * change the keys now anyway. */ wpa_request_new_ptk(hapd, sta); } else if (key_info & WPA_KEY_INFO_KEY_TYPE) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, HOSTAPD_LEVEL_INFO, "received EAPOL-Key Request for new " "4-Way Handshake"); wpa_request_new_ptk(hapd, sta); } else { /* TODO: this could also be a request for STAKey * if Key Data fields contains peer MAC address KDE. * STAKey request should have 0xdd <len> 00-0F-AC:2 in * the beginning of Key Data */ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, HOSTAPD_LEVEL_INFO, "received EAPOL-Key Request for GTK " "rekeying"); wpa_request_new_ptk(hapd, sta); eloop_cancel_timeout(wpa_rekey_gtk, hapd, NULL); wpa_rekey_gtk(hapd, NULL); } } else { /* Do not allow the same key replay counter to be reused. */ sm->key_replay_counter_valid = FALSE; } free(sm->last_rx_eapol_key); sm->last_rx_eapol_key = malloc(data_len); if (sm->last_rx_eapol_key == NULL) return; memcpy(sm->last_rx_eapol_key, data, data_len); sm->last_rx_eapol_key_len = data_len; sm->EAPOLKeyReceived = TRUE; sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE); sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST); memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN); wpa_sm_step(sm);}static void wpa_pmk_to_ptk(struct hostapd_data *hapd, const u8 *pmk, const u8 *addr1, const u8 *addr2, const u8 *nonce1, const u8 *nonce2, u8 *ptk, size_t ptk_len){ u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN]; /* PTK = PRF-X(PMK, "Pairwise key expansion", * Min(AA, SA) || Max(AA, SA) || * Min(ANonce, SNonce) || Max(ANonce, SNonce)) */ if (memcmp(addr1, addr2, ETH_ALEN) < 0) { memcpy(data, addr1, ETH_ALEN); memcpy(data + ETH_ALEN, addr2, ETH_ALEN); } else { memcpy(data, addr2, ETH_ALEN); memcpy(data + ETH_ALEN, addr1, ETH_ALEN); } if (memcmp(nonce1, nonce2, WPA_NONCE_LEN) < 0) { memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN); memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2, WPA_NONCE_LEN); } else { memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN); memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1, WPA_NONCE_LEN); } sha1_prf(pmk, WPA_PMK_LEN, "Pairwise key expansion", data, sizeof(data), ptk, ptk_len); if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL)) { hostapd_hexdump("PMK", pmk, WPA_PMK_LEN); hostapd_hexdump("PTK", ptk, ptk_len); }}static void wpa_gmk_to_gtk(struct hostapd_data *hapd, u8 *gmk, u8 *addr, u8 *gnonce, u8 *gtk, size_t gtk_len){ u8 data[ETH_ALEN + WPA_NONCE_LEN]; /* GTK = PRF-X(GMK, "Group key expansion", AA || GNonce) */ memcpy(data, addr, ETH_ALEN); memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN); sha1_prf(gmk, WPA_GMK_LEN, "Group key expansion", data, sizeof(data), gtk, gtk_len); if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL)) { hostapd_hexdump("GMK", gmk, WPA_GMK_LEN); hostapd_hexdump("GTK", gtk, gtk_len); }}static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx){ struct hostapd_data *hapd = eloop_ctx; struct sta_info *sta = timeout_ctx; if (!sta->wpa_sm || !(sta->flags & WLAN_STA_ASSOC)) return; hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, HOSTAPD_LEVEL_DEBUG, "EAPOL-Key timeout"); sta->wpa_sm->TimeoutEvt = TRUE; wpa_sm_step(sta->wpa_sm);}static int wpa_calc_eapol_key_mic(int ver, u8 *key, u8 *data, size_t len, u8 *mic){ u8 hash[SHA1_MAC_LEN]; switch (ver) { case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4: hmac_md5(key, 16, data, len, mic); break; case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES: hmac_sha1(key, 16, data, len, hash); memcpy(mic, hash, MD5_MAC_LEN); break; default: return -1; } return 0;}static void wpa_send_eapol(struct hostapd_data *hapd, struct sta_info *sta, int secure, int mic, int ack, int install, int pairwise, u8 *key_rsc, u8 *nonce, u8 *ie, size_t ie_len, u8 *gtk, size_t gtk_len, int keyidx){ struct wpa_state_machine *sm = sta->wpa_sm; struct ieee802_1x_hdr *hdr; struct wpa_eapol_key *key; size_t len; int key_info, alg; int timeout_ms; int key_data_len, pad_len = 0; u8 *buf, *pos; if (sm == NULL) return; len = sizeof(struct ieee802_1x_hdr) + sizeof(struct wpa_eapol_key); if (sta->wpa == WPA_VERSION_WPA2) { key_data_len = ie_len + gtk_len; if (gtk_len) key_data_len += 2 + RSN_SELECTOR_LEN + 2; } else { if (pairwise) { /* WPA does not include GTK in 4-Way Handshake */ gtk = NULL; gtk_len = 0; /* key_rsc is for group key, so mask it out in case of * WPA Pairwise key negotiation. */ key_rsc = NULL; } key_data_len = ie_len + gtk_len; } if (sta->pairwise == WPA_CIPHER_CCMP) { key_info = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; if (gtk) { pad_len = key_data_len % 8; if (pad_len) pad_len = 8 - pad_len; key_data_len += pad_len + 8; } } else { key_info = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; } len += key_data_len; hdr = malloc(len); if (hdr == NULL) return; memset(hdr, 0, len); hdr->version = EAPOL_VERSION; hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; hdr->length = htons(len - sizeof(*hdr)); key = (struct wpa_eapol_key *) (hdr + 1); key->type = sta->wpa == WPA_VERSION_WPA2 ? EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; if (secure) key_info |= WPA_KEY_INFO_SECURE; if (mic) key_info |= WPA_KEY_INFO_MIC; if (ack) key_info |= WPA_KEY_INFO_ACK; if (install) key_info |= WPA_KEY_INFO_INSTALL; if (pairwise) key_info |= WPA_KEY_INFO_KEY_TYPE; if (gtk && sta->wpa == WPA_VERSION_WPA2) key_info |= WPA_KEY_INFO_ENCR_KEY_DATA; if (sta->wpa != WPA_VERSION_WPA2) { if (pairwise) keyidx = 0; key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT; } key->key_info = htons(key_info); alg = pairwise ? sta->pairwise : hapd->conf->wpa_group; switch (alg) { case WPA_CIPHER_CCMP: key->key_length = htons(16); break; case WPA_CIPHER_TKIP: key->key_length = htons(32); break; case WPA_CIPHER_WEP40: key->key_length = htons(5); break; case WPA_CIPHER_WEP104: key->key_length = htons(13); break; } inc_byte_array(sm->key_replay_counter, WPA_REPLAY_COUNTER_LEN); memcpy(key->replay_counter, sm->key_replay_counter, WPA_REPLAY_COUNTER_LEN); sm->key_replay_counter_valid = TRUE; if (nonce) memcpy(key->key_nonce, nonce, WPA_NONCE_LEN); if (key_rsc) memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN); if (ie && !gtk) { memcpy(key + 1, ie, ie_len); key->key_data_length = htons(ie_len); } else if (gtk) { buf = malloc(key_data_len); if (buf == NULL) { free(hdr); return; } memset(buf, 0, key_data_len); pos = buf; if (ie) { memcpy(pos, ie, ie_len); pos += ie_len; } if (sta->wpa == WPA_VERSION_WPA2) { *pos++ = WLAN_EID_GENERIC; *pos++ = RSN_SELECTOR_LEN + 2 + gtk_len; memcpy(pos, RSN_KEY_DATA_GROUPKEY, RSN_SELECTOR_LEN); pos += RSN_SELECTOR_LEN; *pos++ = keyidx & 0x03; *pos++ = 0; } memcpy(pos, gtk, gtk_len); pos += gtk_len; if (pad_len) *pos++ = 0xdd; if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL)) { hostapd_hexdump("Plaintext EAPOL-Key Key Data", buf, key_data_len); } if (key_info & WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { aes_wrap(sm->PTK.encr_key, (key_data_len - 8) / 8, buf, (u8 *) (key + 1)); key->key_data_length = htons(key_data_len); } else { u8 ek[32]; memcpy(key->key_iv, hapd->wpa_auth->Counter + WPA_NONCE_LEN - 16, 16); inc_byte_array(hapd->wpa_auth->Counter, WPA_NONCE_LEN); memcpy(ek, key->key_iv, 16); memcpy(ek + 16, sm->PTK.encr_key, 16); memcpy(key + 1, buf, key_data_len); rc4_skip(ek, 32, 256, (u8 *) (key + 1), key_data_len); key->key_data_length = htons(key_data_len); } free(buf); } if (mic) { if (!sm->PTK_valid) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, HOSTAPD_LEVEL_DEBUG, "PTK not valid " "when sending EAPOL-Key frame"); free(hdr); return; } wpa_calc_eapol_key_mic(key_info & WPA_KEY_INFO_TYPE_MASK, sm->PTK.mic_key, (u8 *) hdr, len, key->key_mic); } if (sta->eapol_sm) sta->eapol_sm->dot1xAuthEapolFramesTx++; hostapd_send_eapol(hapd, sta->addr, (u8 *) hdr, len, sm->pairwise_set); free(hdr); timeout_ms = pairwise ? dot11RSNAConfigPairwiseUpdateTimeOut : dot11RSNAConfigGroupUpdateTimeOut; eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000, wpa_send_eapol_timeout, hapd, sta);}static int wpa_verify_key_mic(struct wpa_ptk *PTK, u8 *data, size_t data_len){ struct ieee802_1x_hdr *hdr; struct wpa_eapol_key *key; u16 key_info; int type, ret = 0; u8 mic[16]; if (data_len < sizeof(*hdr) + sizeof(*key)) return -1; hdr = (struct ieee802_1x_hdr *) data; key = (struct wpa_eapol_key *) (hdr + 1); key_info = ntohs(key->key_info); type = key_info & WPA_KEY_INFO_TYPE_MASK; memcpy(mic, key->key_mic, 16); memset(key->key_mic, 0, 16); if (wpa_calc_eapol_key_mic(key_info & WPA_KEY_INFO_TYPE_MASK, PTK->mic_key, data, data_len, key->key_mic) || memcmp(mic, key->key_mic, 16) != 0) ret = -1; memcpy(key->key_mic, mic, 16); return ret;}void wpa_sm_event(struct hostapd_data *hapd, struct sta_info *sta, wpa_event event){ struct wpa_state_machine *sm = sta->wpa_sm; hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, HOSTAPD_LEVEL_DEBUG, "event %d notification", event); if (sm == NULL) return; switch (event) { case WPA_AUTH: case WPA_ASSOC: break; case WPA_DEAUTH: case WPA_DISASSOC: sm->DeauthenticationRequest = TRUE; break; case WPA_REAUTH: case WPA_REAUTH_EAPOL: sm->ReAuthenticationRequest = TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -