⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wpa.c

📁 WPA在Linux下实现的原代码 WPA在Linux下实现的原代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			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;	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;}static void wpa_report_ie_mismatch(struct wpa_sm *sm,				   const char *reason, const u8 *src_addr,				   const u8 *wpa_ie, size_t wpa_ie_len,				   const u8 *rsn_ie, size_t rsn_ie_len){	wpa_msg(sm->ctx->ctx, MSG_WARNING, "WPA: %s (src=" MACSTR ")",		reason, MAC2STR(src_addr));	if (sm->ap_wpa_ie) {		wpa_hexdump(MSG_INFO, "WPA: WPA IE in Beacon/ProbeResp",			    sm->ap_wpa_ie, sm->ap_wpa_ie_len);	}	if (wpa_ie) {		if (!sm->ap_wpa_ie) {			wpa_printf(MSG_INFO, "WPA: No WPA IE in "				   "Beacon/ProbeResp");		}		wpa_hexdump(MSG_INFO, "WPA: WPA IE in 3/4 msg",			    wpa_ie, wpa_ie_len);	}	if (sm->ap_rsn_ie) {		wpa_hexdump(MSG_INFO, "WPA: RSN IE in Beacon/ProbeResp",			    sm->ap_rsn_ie, sm->ap_rsn_ie_len);	}	if (rsn_ie) {		if (!sm->ap_rsn_ie) {			wpa_printf(MSG_INFO, "WPA: No RSN IE in "				   "Beacon/ProbeResp");		}		wpa_hexdump(MSG_INFO, "WPA: RSN IE in 3/4 msg",			    rsn_ie, rsn_ie_len);	}	wpa_sm_disassociate(sm, REASON_IE_IN_4WAY_DIFFERS);	wpa_sm_req_scan(sm, 0, 0);}static int wpa_supplicant_validate_ie(struct wpa_sm *sm,				      const unsigned char *src_addr,				      struct wpa_eapol_ie_parse *ie){	struct wpa_ssid *ssid = sm->cur_ssid;	if (sm->ap_wpa_ie == NULL && sm->ap_rsn_ie == NULL) {		wpa_printf(MSG_DEBUG, "WPA: No WPA/RSN IE for this AP known. "			   "Trying to get from scan results");		if (wpa_sm_get_beacon_ie(sm) < 0) {			wpa_printf(MSG_WARNING, "WPA: Could not find AP from "				   "the scan results");		} else {			wpa_printf(MSG_DEBUG, "WPA: Found the current AP from "				   "updated scan results");		}	}	if (ie->wpa_ie == NULL && ie->rsn_ie == NULL &&	    (sm->ap_wpa_ie || sm->ap_rsn_ie)) {		wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match "				       "with IE in Beacon/ProbeResp (no IE?)",				       src_addr, ie->wpa_ie, ie->wpa_ie_len,				       ie->rsn_ie, ie->rsn_ie_len);		return -1;	}	if ((ie->wpa_ie && sm->ap_wpa_ie &&	     (ie->wpa_ie_len != sm->ap_wpa_ie_len ||	      memcmp(ie->wpa_ie, sm->ap_wpa_ie, ie->wpa_ie_len) != 0)) ||	    (ie->rsn_ie && sm->ap_rsn_ie &&	     (ie->rsn_ie_len != sm->ap_rsn_ie_len ||	      memcmp(ie->rsn_ie, sm->ap_rsn_ie, ie->rsn_ie_len) != 0))) {		wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match "				       "with IE in Beacon/ProbeResp",				       src_addr, ie->wpa_ie, ie->wpa_ie_len,				       ie->rsn_ie, ie->rsn_ie_len);		return -1;	}	if (sm->proto == WPA_PROTO_WPA &&	    ie->rsn_ie && sm->ap_rsn_ie == NULL &&	    ssid && (ssid->proto & WPA_PROTO_RSN)) {		wpa_report_ie_mismatch(sm, "Possible downgrade attack "				       "detected - RSN was enabled and RSN IE "				       "was in msg 3/4, but not in "				       "Beacon/ProbeResp",				       src_addr, ie->wpa_ie, ie->wpa_ie_len,				       ie->rsn_ie, ie->rsn_ie_len);		return -1;	}	return 0;}static int wpa_supplicant_send_4_of_4(struct wpa_sm *sm,				      const unsigned char *dst,				      const struct wpa_eapol_key *key,				      u16 ver, u16 key_info){	size_t rlen;	struct wpa_eapol_key *reply;	u8 *rbuf;	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,				  sizeof(*reply), &rlen, (void *) &reply);	if (rbuf == NULL)		return -1;	reply->type = sm->proto == WPA_PROTO_RSN ?		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;	key_info &= WPA_KEY_INFO_SECURE;	key_info |= ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC;	WPA_PUT_BE16(reply->key_info, key_info);	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, 0);	wpa_printf(MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4");	wpa_eapol_key_send(sm, sm->ptk.kck, ver, dst, ETH_P_EAPOL,			   rbuf, rlen, reply->key_mic);	return 0;}static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,					  const struct wpa_eapol_key *key,					  int extra_len, u16 ver){	u16 key_info, keylen, len;	const u8 *pos;	struct wpa_eapol_ie_parse ie;	wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);	wpa_printf(MSG_DEBUG, "WPA: RX message 3 of 4-Way Handshake from "		   MACSTR " (ver=%d)", MAC2STR(sm->bssid), ver);	key_info = WPA_GET_BE16(key->key_info);	pos = (const u8 *) (key + 1);	len = WPA_GET_BE16(key->key_data_length);	wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", pos, len);	wpa_supplicant_parse_ies(pos, len, &ie);	if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {		wpa_printf(MSG_WARNING, "WPA: GTK IE in unencrypted key data");		return;	}	if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0)		return;	if (memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) {		wpa_printf(MSG_WARNING, "WPA: ANonce from message 1 of 4-Way "			   "Handshake differs from 3 of 4-Way Handshake - drop"			   " packet (src=" MACSTR ")", MAC2STR(sm->bssid));		return;	}	keylen = WPA_GET_BE16(key->key_length);	switch (sm->pairwise_cipher) {	case WPA_CIPHER_CCMP:		if (keylen != 16) {			wpa_printf(MSG_WARNING, "WPA: Invalid CCMP key length "				   "%d (src=" MACSTR ")",				   keylen, MAC2STR(sm->bssid));			return;		}		break;	case WPA_CIPHER_TKIP:		if (keylen != 32) {			wpa_printf(MSG_WARNING, "WPA: Invalid TKIP key length "				   "%d (src=" MACSTR ")",				   keylen, MAC2STR(sm->bssid));			return;		}		break;	}	if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info))		return;	/* SNonce was successfully used in msg 3/4, so mark it to be renewed	 * for the next 4-Way Handshake. If msg 3 is received again, the old	 * SNonce will still be used to avoid changing PTK. */	sm->renew_snonce = 1;	if (key_info & WPA_KEY_INFO_INSTALL) {		wpa_supplicant_install_ptk(sm, key);	}	if (key_info & WPA_KEY_INFO_SECURE) {		/* MLME.SETPROTECTION.request(TA, Tx_Rx) */		eapol_sm_notify_portValid(sm->eapol, TRUE);	}	wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);	if (ie.gtk &&	    wpa_supplicant_pairwise_gtk(sm, key,					ie.gtk, ie.gtk_len, key_info) < 0) {		wpa_printf(MSG_INFO, "RSN: Failed to configure GTK");	}}static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm,					     const u8 *keydata,					     size_t keydatalen,					     int key_info,					     struct wpa_gtk_data *gd){	int maxkeylen;	struct wpa_eapol_ie_parse ie;	wpa_hexdump(MSG_DEBUG, "RSN: msg 1/2 key data", keydata, keydatalen);	wpa_supplicant_parse_ies(keydata, keydatalen, &ie);	if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {		wpa_printf(MSG_WARNING, "WPA: GTK IE in unencrypted key data");		return -1;	}	if (ie.gtk == NULL) {		wpa_printf(MSG_INFO, "WPA: No GTK IE in Group Key msg 1/2");		return -1;	}	maxkeylen = gd->gtk_len = ie.gtk_len - 2;	if (wpa_supplicant_check_group_cipher(sm->group_cipher,					      gd->gtk_len, maxkeylen,					      &gd->key_rsc_len, &gd->alg))		return -1;	wpa_hexdump(MSG_DEBUG, "RSN: received GTK in group key handshake",		    ie.gtk, ie.gtk_len);	gd->keyidx = ie.gtk[0] & 0x3;	gd->tx = wpa_supplicant_gtk_tx_bit_workaround(sm,						      !!(ie.gtk[0] & BIT(2)));	if (ie.gtk_len - 2 > sizeof(gd->gtk)) {		wpa_printf(MSG_INFO, "RSN: Too long GTK in GTK IE "			   "(len=%lu)", (unsigned long) ie.gtk_len - 2);		return -1;	}	memcpy(gd->gtk, ie.gtk + 2, ie.gtk_len - 2);	return 0;}static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm,					     const struct wpa_eapol_key *key,					     size_t keydatalen, int key_info,					     int extra_len, u16 ver,					     struct wpa_gtk_data *gd){	int maxkeylen;	u8 ek[32];	gd->gtk_len = WPA_GET_BE16(key->key_length);	maxkeylen = keydatalen;	if (keydatalen > extra_len) {		wpa_printf(MSG_INFO, "WPA: Truncated EAPOL-Key packet:"			   " key_data_length=%lu > extra_len=%d",			   (unsigned long) keydatalen, extra_len);		return -1;	}	if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES)		maxkeylen -= 8;	if (wpa_supplicant_check_group_cipher(sm->group_cipher,					      gd->gtk_len, maxkeylen,					      &gd->key_rsc_len, &gd->alg))		return -1;	gd->keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>		WPA_KEY_INFO_KEY_INDEX_SHIFT;	if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) {		memcpy(ek, key->key_iv, 16);		memcpy(ek + 16, sm->ptk.kek, 16);		if (keydatalen > sizeof(gd->gtk)) {			wpa_printf(MSG_WARNING, "WPA: RC4 key data "				   "too long (%lu)",				   (unsigned long) keydatalen);			return -1;		}		memcpy(gd->gtk, key + 1, keydatalen);		rc4_skip(ek, 32, 256, gd->gtk, keydatalen);	} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {		if (keydatalen % 8) {			wpa_printf(MSG_WARNING, "WPA: Unsupported AES-WRAP "				   "len %lu", (unsigned long) keydatalen);			return -1;		}		if (maxkeylen > sizeof(gd->gtk)) {			wpa_printf(MSG_WARNING, "WPA: AES-WRAP key data "				   "too long (keydatalen=%lu maxkeylen=%lu)",				   (unsigned long) keydatalen,				   (unsigned long) maxkeylen);			return -1;		}		if (aes_unwrap(sm->ptk.kek, maxkeylen / 8,			       (const u8 *) (key + 1), gd->gtk)) {			wpa_printf(MSG_WARNING, "WPA: AES unwrap "				   "failed - could not decrypt GTK");			return -1;		}	}	gd->tx = wpa_supplicant_gtk_tx_bit_workaround(		sm, !!(key_info & WPA_KEY_INFO_TXRX));	return 0;}static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm,				      const struct wpa_eapol_key *key,				      int ver, u16 key_info){	size_t rlen;	struct wpa_eapol_key *reply;	u8 *rbuf;	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,				  sizeof(*reply), &rlen, (void *) &reply);	if (rbuf == NULL)		return -1;	reply->type = sm->proto == WPA_PROTO_RSN ?		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;	key_info &= WPA_KEY_INFO_KEY_INDEX_MASK;	key_info |= ver | WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE;	WPA_PUT_BE16(reply->key_info, key_info);	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, 0);	wpa_printf(MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2");	wpa_eapol_key_send(sm, sm->ptk.kck, ver, sm->bssid, ETH_P_EAPOL,			   rbuf, rlen, reply->key_mic);	return 0;}static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,					  const unsigned char *src_addr,					  const struct wpa_eapol_key *key,					  int extra_len, u16 ver){	u16 key_info, keydatalen;	int rekey;	struct wpa_gtk_data gd;	memset(&gd, 0, sizeof(gd));	rekey = wpa_sm_get_state(sm) == WPA_COMPLETED;	wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);	wpa_printf(MSG_DEBUG, "WPA: RX message 1 of Group Key Handshake from "		   MACSTR " (ver=%d)", MAC2STR(src_addr), ver);	key_info = WPA_GET_BE16(key->key_info);	keydatalen = WPA_GET_BE16(key->key_data_length);	if (sm->proto == WPA_PROTO_RSN) {		if (wpa_supplicant_process_1_of_2_rsn(sm,						      (const u8 *) (key + 1),						      keydatalen, key_info,						      &gd))			return;	} else {		if (wpa_supplicant_process_1_of_2_wpa(sm, key, keydatalen,						      key_info, extra_len,						      ver, &gd))			return;	}	if (wpa_supplicant_install_gtk(sm, &gd, key->key_rsc) ||	    wpa_supplicant_send_2_of_2(sm, key, ver, key_info))		return;	if (rekey) {		wpa_msg(sm->ctx->ctx, MSG_INFO, "WPA: Group rekeying "			"completed with " MACSTR " [GTK=%s]",			MAC2STR(sm->bssid), wpa_cipher_txt(sm->group_cipher));		wpa_sm_set_state(sm, WPA_COMPLETED);	} else {		wpa_supplicant_key_neg_complete(sm, sm->bssid,						key_info &						WPA_KEY_INFO_SECURE);	}}static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm,					       struct wpa_eapol_key *key,					       u16 ver,					       const u8 *buf, size_t len){	u8 mic[16];	int ok = 0;	memcpy(mic, key->key_mic, 16);	if (sm->tptk_set) {		memset(key->key_mic, 0, 16);		wpa_eapol_key_mic(sm->tptk.kck, ver, buf, len,				  key->key_mic);		if (memcmp(mic, key->key_mic, 16) != 0) {			wpa_printf(MSG_WARNING, "WPA: Invalid EAPOL-Key MIC "				   "when using TPTK - ignoring TPTK");		} else {			ok = 1;			sm->tptk_set = 0;			sm->ptk_set = 1;			memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk));		}	}	if (!ok && sm->ptk_set) {		memset(key->key_mic, 0, 16);		wpa_eapol_key_mic(sm->ptk.kck, ver, buf, len,				  key->key_mic);		if (memcmp(mic, key->key_mic, 16) != 0) {			wpa_printf(MSG_WARNING, "WPA: Invalid EAPOL-Key MIC "				   "- dropping packet");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -