📄 wpa.c
字号:
wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data " "underflow (ie=%d len=%d pos=%d)", pos[0], pos[1], (int) (pos - buf)); wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data", buf, len); ret = -1; break; } if (*pos == RSN_INFO_ELEM) { ie->rsn_ie = pos; ie->rsn_ie_len = pos[1] + 2; } else if (*pos == GENERIC_INFO_ELEM) { ret = wpa_supplicant_parse_generic(pos, end, ie); if (ret < 0) break; if (ret > 0) { ret = 0; break; } } else { wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key " "Key Data IE", pos, 2 + pos[1]); } } return ret;}static int wpa_supplicant_get_pmk(struct wpa_sm *sm, const unsigned char *src_addr, const u8 *pmkid){ int abort_cached = 0; if (pmkid && !sm->cur_pmksa) { /* When using drivers that generate RSN IE, wpa_supplicant may * not have enough time to get the association information * event before receiving this 1/4 message, so try to find a * matching PMKSA cache entry here. */ sm->cur_pmksa = pmksa_cache_get(sm, src_addr, pmkid); if (sm->cur_pmksa) { wpa_printf(MSG_DEBUG, "RSN: found matching PMKID from " "PMKSA cache"); } else { wpa_printf(MSG_DEBUG, "RSN: no matching PMKID found"); abort_cached = 1; } } if (pmkid && sm->cur_pmksa && memcmp(pmkid, sm->cur_pmksa->pmkid, PMKID_LEN) == 0) { wpa_hexdump(MSG_DEBUG, "RSN: matched PMKID", pmkid, PMKID_LEN); wpa_sm_set_pmk_from_pmksa(sm); wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from PMKSA cache", sm->pmk, sm->pmk_len); eapol_sm_notify_cached(sm->eapol); } else if (sm->key_mgmt == WPA_KEY_MGMT_IEEE8021X && sm->eapol) { int res, pmk_len; pmk_len = PMK_LEN; res = eapol_sm_get_key(sm->eapol, sm->pmk, PMK_LEN);#ifdef EAP_LEAP if (res) { res = eapol_sm_get_key(sm->eapol, sm->pmk, 16); pmk_len = 16; }#endif /* EAP_LEAP */ if (res == 0) { wpa_hexdump_key(MSG_DEBUG, "WPA: PMK from EAPOL state " "machines", sm->pmk, pmk_len); sm->pmk_len = pmk_len; pmksa_cache_add(sm, sm->pmk, pmk_len, src_addr, sm->own_addr, sm->cur_ssid); if (!sm->cur_pmksa && pmkid && pmksa_cache_get(sm, src_addr, pmkid)) { wpa_printf(MSG_DEBUG, "RSN: the new PMK " "matches with the PMKID"); abort_cached = 0; } } else { wpa_msg(sm->ctx->ctx, MSG_WARNING, "WPA: Failed to get master session key from " "EAPOL state machines"); wpa_msg(sm->ctx->ctx, MSG_WARNING, "WPA: Key handshake aborted"); if (sm->cur_pmksa) { wpa_printf(MSG_DEBUG, "RSN: Cancelled PMKSA " "caching attempt"); sm->cur_pmksa = NULL; abort_cached = 1; } else { return -1; } } } if (abort_cached && sm->key_mgmt == WPA_KEY_MGMT_IEEE8021X) { /* Send EAPOL-Start to trigger full EAP authentication. */ u8 *buf; size_t buflen; wpa_printf(MSG_DEBUG, "RSN: no PMKSA entry found - trigger " "full EAP authentication"); buf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START, NULL, 0, &buflen, NULL); if (buf) { wpa_sm_ether_send(sm, sm->bssid, ETH_P_EAPOL, buf, buflen); free(buf); } return -1; } return 0;}static int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, const struct wpa_eapol_key *key, int ver){ size_t rlen; struct wpa_eapol_key *reply; struct wpa_ptk *ptk; u8 buf[8], *rbuf, *wpa_ie; int wpa_ie_len; if (sm->assoc_wpa_ie == NULL) { wpa_printf(MSG_WARNING, "WPA: No assoc_wpa_ie set - cannot " "generate msg 2/4"); return -1; } wpa_ie = sm->assoc_wpa_ie; wpa_ie_len = sm->assoc_wpa_ie_len; wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len); rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, sizeof(*reply) + wpa_ie_len, &rlen, (void *) &reply); if (rbuf == NULL) return -1; reply->type = sm->proto == WPA_PROTO_RSN ? EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; WPA_PUT_BE16(reply->key_info, ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC); if (sm->proto == WPA_PROTO_RSN) WPA_PUT_BE16(reply->key_length, 0); else memcpy(reply->key_length, key->key_length, 2); memcpy(reply->replay_counter, key->replay_counter, WPA_REPLAY_COUNTER_LEN); WPA_PUT_BE16(reply->key_data_length, wpa_ie_len); memcpy(reply + 1, wpa_ie, wpa_ie_len); if (sm->renew_snonce) { if (hostapd_get_rand(sm->snonce, WPA_NONCE_LEN)) { wpa_msg(sm->ctx->ctx, MSG_WARNING, "WPA: Failed to get random data for SNonce"); free(rbuf); return -1; } sm->renew_snonce = 0; wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce", sm->snonce, WPA_NONCE_LEN); } memcpy(reply->key_nonce, sm->snonce, WPA_NONCE_LEN); /* Calculate PTK which will be stored as a temporary PTK until it has * been verified when processing message 3/4. */ ptk = &sm->tptk; wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, sm->own_addr, sm->bssid, sm->snonce, key->key_nonce, (u8 *) ptk, sizeof(*ptk)); /* Supplicant: swap tx/rx Mic keys */ memcpy(buf, ptk->u.auth.tx_mic_key, 8); memcpy(ptk->u.auth.tx_mic_key, ptk->u.auth.rx_mic_key, 8); memcpy(ptk->u.auth.rx_mic_key, buf, 8); sm->tptk_set = 1; wpa_printf(MSG_DEBUG, "WPA: Sending EAPOL-Key 2/4"); wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL, rbuf, rlen, reply->key_mic); return 0;}static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, const unsigned char *src_addr, const struct wpa_eapol_key *key, u16 ver){ struct wpa_eapol_ie_parse ie; if (wpa_sm_get_ssid(sm) == NULL) { wpa_printf(MSG_WARNING, "WPA: No SSID info found (msg 1 of " "4)."); return; } wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE); wpa_printf(MSG_DEBUG, "WPA: RX message 1 of 4-Way Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver); memset(&ie, 0, sizeof(ie)); if (sm->proto == WPA_PROTO_RSN) { /* RSN: msg 1/4 should contain PMKID for the selected PMK */ const u8 *buf = (const u8 *) (key + 1); size_t len = WPA_GET_BE16(key->key_data_length); wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", buf, len); wpa_supplicant_parse_ies(buf, len, &ie); if (ie.pmkid) { wpa_hexdump(MSG_DEBUG, "RSN: PMKID from " "Authenticator", ie.pmkid, PMKID_LEN); } } if (wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid)) return; if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver)) return; memcpy(sm->anonce, key->key_nonce, WPA_NONCE_LEN);}static void wpa_sm_start_preauth(void *eloop_ctx, void *timeout_ctx){ struct wpa_sm *sm = eloop_ctx; rsn_preauth_candidate_process(sm);}static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm, const u8 *addr, int secure){ wpa_msg(sm->ctx->ctx, MSG_INFO, "WPA: Key negotiation completed with " MACSTR " [PTK=%s GTK=%s]", MAC2STR(addr), wpa_cipher_txt(sm->pairwise_cipher), wpa_cipher_txt(sm->group_cipher)); eloop_cancel_timeout(sm->ctx->scan, sm->ctx->ctx, NULL); wpa_sm_cancel_auth_timeout(sm); wpa_sm_set_state(sm, WPA_COMPLETED); if (secure) { /* MLME.SETPROTECTION.request(TA, Tx_Rx) */ eapol_sm_notify_portValid(sm->eapol, TRUE); if (sm->key_mgmt == WPA_KEY_MGMT_PSK) eapol_sm_notify_eap_success(sm->eapol, TRUE); /* * Start preauthentication after a short wait to avoid a * possible race condition between the data receive and key * configuration after the 4-Way Handshake. This increases the * likelyhood of the first preauth EAPOL-Start frame getting to * the target AP. */ eloop_register_timeout(1, 0, wpa_sm_start_preauth, sm, NULL); } if (sm->cur_pmksa && sm->cur_pmksa->opportunistic) { wpa_printf(MSG_DEBUG, "RSN: Authenticator accepted " "opportunistic PMKSA entry - marking it valid"); sm->cur_pmksa->opportunistic = 0; }}static int wpa_supplicant_install_ptk(struct wpa_sm *sm, const struct wpa_eapol_key *key){ int keylen, rsclen; wpa_alg alg; const u8 *key_rsc; u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; wpa_printf(MSG_DEBUG, "WPA: Installing PTK to the driver."); switch (sm->pairwise_cipher) { case WPA_CIPHER_CCMP: alg = WPA_ALG_CCMP; keylen = 16; rsclen = 6; break; case WPA_CIPHER_TKIP: alg = WPA_ALG_TKIP; keylen = 32; rsclen = 6; break; case WPA_CIPHER_NONE: wpa_printf(MSG_DEBUG, "WPA: Pairwise Cipher Suite: " "NONE - do not use pairwise keys"); return 0; default: wpa_printf(MSG_WARNING, "WPA: Unsupported pairwise cipher %d", sm->pairwise_cipher); return -1; } if (sm->proto == WPA_PROTO_RSN) { key_rsc = null_rsc; } else { key_rsc = key->key_rsc; wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, rsclen); } if (wpa_sm_set_key(sm, alg, sm->bssid, 0, 1, key_rsc, rsclen, (u8 *) &sm->ptk.tk1, keylen) < 0) { wpa_printf(MSG_WARNING, "WPA: Failed to set PTK to the " "driver."); return -1; } return 0;}static int wpa_supplicant_check_group_cipher(int group_cipher, int keylen, int maxkeylen, int *key_rsc_len, wpa_alg *alg){ int ret = 0; switch (group_cipher) { case WPA_CIPHER_CCMP: if (keylen != 16 || maxkeylen < 16) { ret = -1; break; } *key_rsc_len = 6; *alg = WPA_ALG_CCMP; break; case WPA_CIPHER_TKIP: if (keylen != 32 || maxkeylen < 32) { ret = -1; break; } *key_rsc_len = 6; *alg = WPA_ALG_TKIP; break; case WPA_CIPHER_WEP104: if (keylen != 13 || maxkeylen < 13) { ret = -1; break; } *key_rsc_len = 0; *alg = WPA_ALG_WEP; break; case WPA_CIPHER_WEP40: if (keylen != 5 || maxkeylen < 5) { ret = -1; break; } *key_rsc_len = 0; *alg = WPA_ALG_WEP; break; default: wpa_printf(MSG_WARNING, "WPA: Unsupported Group Cipher %d", group_cipher); return -1; } if (ret < 0 ) { wpa_printf(MSG_WARNING, "WPA: Unsupported %s Group Cipher key " "length %d (%d).", wpa_cipher_txt(group_cipher), keylen, maxkeylen); } return ret;}struct wpa_gtk_data { wpa_alg alg; int tx, key_rsc_len, keyidx; u8 gtk[32]; int gtk_len;};static int wpa_supplicant_install_gtk(struct wpa_sm *sm, const struct wpa_gtk_data *gd, const u8 *key_rsc){ const u8 *_gtk = gd->gtk; u8 gtk_buf[32]; wpa_hexdump_key(MSG_DEBUG, "WPA: Group Key", gd->gtk, gd->gtk_len); wpa_printf(MSG_DEBUG, "WPA: Installing GTK to the driver " "(keyidx=%d tx=%d).", gd->keyidx, gd->tx); wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, gd->key_rsc_len); if (sm->group_cipher == WPA_CIPHER_TKIP) { /* Swap Tx/Rx keys for Michael MIC */ memcpy(gtk_buf, gd->gtk, 16); memcpy(gtk_buf + 16, gd->gtk + 24, 8); memcpy(gtk_buf + 24, gd->gtk + 16, 8); _gtk = gtk_buf; } if (sm->pairwise_cipher == WPA_CIPHER_NONE) { if (wpa_sm_set_key(sm, gd->alg, (u8 *) "\xff\xff\xff\xff\xff\xff", gd->keyidx, 1, key_rsc, gd->key_rsc_len, _gtk, gd->gtk_len) < 0) { wpa_printf(MSG_WARNING, "WPA: Failed to set " "GTK to the driver (Group only)."); return -1; } } else if (wpa_sm_set_key(sm, gd->alg, (u8 *) "\xff\xff\xff\xff\xff\xff", gd->keyidx, gd->tx, key_rsc, gd->key_rsc_len, _gtk, gd->gtk_len) < 0) { wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to " "the driver."); return -1; } return 0;}static int wpa_supplicant_gtk_tx_bit_workaround(const struct wpa_sm *sm, int tx){ if (tx && sm->pairwise_cipher != WPA_CIPHER_NONE) { /* Ignore Tx bit for GTK if a pairwise key is used. One AP * seemed to set this bit (incorrectly, since Tx is only when * doing Group Key only APs) and without this workaround, the * data connection does not work because wpa_supplicant * configured non-zero keyidx to be used for unicast. */ wpa_printf(MSG_INFO, "WPA: Tx bit set for GTK, but pairwise " "keys are used - ignore Tx bit"); return 0; } return tx;}static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm, const struct wpa_eapol_key *key, const u8 *gtk, int gtk_len, int key_info){ struct wpa_gtk_data gd; /* * IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames - Figure 43x * GTK KDE format: * KeyID[bits 0-1], Tx [bit 2], Reserved [bits 3-7] * Reserved [bits 0-7] * GTK */ memset(&gd, 0, sizeof(gd)); wpa_hexdump_key(MSG_DEBUG, "RSN: received GTK in pairwise handshake",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -