📄 wpa.c
字号:
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); os_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, const u8 *nonce, const u8 *wpa_ie, size_t wpa_ie_len, struct wpa_ptk *ptk){ size_t rlen; struct wpa_eapol_key *reply; u8 *rbuf; if (wpa_ie == NULL) { wpa_printf(MSG_WARNING, "WPA: No wpa_ie set - cannot " "generate msg 2/4"); return -1; } 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 os_memcpy(reply->key_length, key->key_length, 2); os_memcpy(reply->replay_counter, key->replay_counter, WPA_REPLAY_COUNTER_LEN); WPA_PUT_BE16(reply->key_data_length, wpa_ie_len); os_memcpy(reply + 1, wpa_ie, wpa_ie_len); os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN); 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; struct wpa_ptk *ptk; u8 buf[8]; 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); os_memset(&ie, 0, sizeof(ie));#ifndef CONFIG_NO_WPA2 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); } }#endif /* CONFIG_NO_WPA2 */ if (wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid)) return; 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"); return; } sm->renew_snonce = 0; wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce", 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, "Pairwise key expansion", sm->own_addr, sm->bssid, sm->snonce, key->key_nonce, (u8 *) ptk, sizeof(*ptk)); /* Supplicant: swap tx/rx Mic keys */ os_memcpy(buf, ptk->u.auth.tx_mic_key, 8); os_memcpy(ptk->u.auth.tx_mic_key, ptk->u.auth.rx_mic_key, 8); os_memcpy(ptk->u.auth.rx_mic_key, buf, 8); sm->tptk_set = 1; if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce, sm->assoc_wpa_ie, sm->assoc_wpa_ie_len, ptk)) return; os_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) { wpa_sm_mlme_setprotection( sm, addr, MLME_SETPROTECTION_PROTECT_TYPE_RX_TX, MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); 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 */ os_memcpy(gtk_buf, gd->gtk, 16); os_memcpy(gtk_buf + 16, gd->gtk + 24, 8); os_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, size_t gtk_len, int key_info){#ifndef CONFIG_NO_WPA2 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 */ os_memset(&gd, 0, sizeof(gd)); wpa_hexdump_key(MSG_DEBUG, "RSN: received GTK in pairwise handshake", gtk, gtk_len); if (gtk_len < 2 || gtk_len - 2 > sizeof(gd.gtk)) return -1; gd.keyidx = gtk[0] & 0x3; gd.tx = wpa_supplicant_gtk_tx_bit_workaround(sm, !!(gtk[0] & BIT(2))); gtk += 2; gtk_len -= 2; os_memcpy(gd.gtk, gtk, gtk_len); gd.gtk_len = gtk_len; if (wpa_supplicant_check_group_cipher(sm->group_cipher, gtk_len, gtk_len, &gd.key_rsc_len, &gd.alg) || wpa_supplicant_install_gtk(sm, &gd, key->key_rsc)) { wpa_printf(MSG_DEBUG, "RSN: Failed to install GTK"); return -1; } wpa_supplicant_key_neg_complete(sm, sm->bssid, key_info & WPA_KEY_INFO_SECURE); return 0;#else /* CONFIG_NO_WPA2 */ return -1;#endif /* CONFIG_NO_WPA2 */}static int ieee80211w_set_keys(struct wpa_sm *sm, struct wpa_eapol_ie_parse *ie){#ifdef CONFIG_IEEE80211W if (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) return 0; if (ie->igtk) { const struct wpa_igtk_kde *igtk; u16 keyidx; if (ie->igtk_len != sizeof(*igtk)) return -1; igtk = (const struct wpa_igtk_kde *) ie->igtk; keyidx = WPA_GET_LE16(igtk->keyid); wpa_printf(MSG_DEBUG, "WPA: IGTK keyid %d " "pn %02x%02x%02x%02x%02x%02x", keyidx, MAC2STR(igtk->pn)); wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK", igtk->igtk, WPA_IGTK_LEN); if (keyidx > 4095) { wpa_printf(MSG_WARNING, "WPA: Invalid IGTK KeyID %d", keyidx); return -1; } if (wpa_sm_set_key(sm, WPA_ALG_IGTK, (u8 *) "\xff\xff\xff\xff\xff\xff", keyidx, 0, igtk->pn, sizeof(igtk->pn), igtk->igtk, WPA_IGTK_LEN) < 0) { wpa_printf(MSG_WARNING, "WPA: Failed to configure IGTK" " to the driver"); return -1; } } if (ie->dhv) { const struct wpa_dhv_kde *dhv; if (ie->dhv_len != sizeof(*dhv)) return -1; dhv = (const struct wpa_dhv_kde *) ie->dhv; wpa_hexdump_key(MSG_DEBUG, "WPA: DHV", dhv->dhv, WPA_DHV_LEN); if (wpa_sm_set_key(sm, WPA_ALG_DHV, (u8 *) "\xff\xff\xff\xff\xff\xff", 0, 0, NULL, 0, dhv->dhv, WPA_DHV_LEN) < 0) { wpa_printf(MSG_WARNING, "WPA: Failed to configure DHV " "to the driver"); return -1; } } return 0;#else /* CONFIG_IEEE80211W */ return 0;#endif /* CONFIG_IEEE80211W */}static void wpa_report_ie_mismatch(struct wpa_sm *sm,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -