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

📄 wpa.c

📁 hostapd源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	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 wpa_authenticator *wpa_auth,			     struct wpa_state_machine *sm,			     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, int encr, int force_version){	struct ieee802_1x_hdr *hdr;	struct wpa_eapol_key *key;	size_t len;	int key_info, alg;	int key_data_len, pad_len = 0;	u8 *buf, *pos;	int version;	len = sizeof(struct ieee802_1x_hdr) + sizeof(struct wpa_eapol_key);	if (force_version)		version = force_version;	else if (sm->pairwise == WPA_CIPHER_CCMP)		version = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;	else		version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;	wpa_printf(MSG_DEBUG, "WPA: Send EAPOL(secure=%d mic=%d ack=%d "		   "install=%d pairwise=%d ie_len=%lu gtk_len=%lu keyidx=%d "		   "encr=%d)",		   secure, mic, ack, install, pairwise, (unsigned long) ie_len,		   (unsigned long) gtk_len, keyidx, encr);	key_data_len = ie_len + gtk_len;	if (sm->wpa == WPA_VERSION_WPA2 && gtk_len)		key_data_len += 2 + RSN_SELECTOR_LEN + 2;	if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {		pad_len = key_data_len % 8;		if (pad_len)			pad_len = 8 - pad_len;		key_data_len += pad_len + 8;	}	len += key_data_len;	hdr = wpa_zalloc(len);	if (hdr == NULL)		return;	hdr->version = wpa_auth->conf.eapol_version;	hdr->type = IEEE802_1X_TYPE_EAPOL_KEY;	hdr->length = htons(len  - sizeof(*hdr));	key = (struct wpa_eapol_key *) (hdr + 1);	key->type = sm->wpa == WPA_VERSION_WPA2 ?		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;	key_info = version;	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 (encr && sm->wpa == WPA_VERSION_WPA2)		key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;	if (sm->wpa != WPA_VERSION_WPA2)		key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT;	key->key_info = htons(key_info);	alg = pairwise ? sm->pairwise : wpa_auth->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 && !encr) {		memcpy(key + 1, ie, ie_len);		key->key_data_length = htons(ie_len);	} else if (encr && (gtk || ie)) {		buf = wpa_zalloc(key_data_len);		if (buf == NULL) {			free(hdr);			return;		}		pos = buf;		if (ie) {			memcpy(pos, ie, ie_len);			pos += ie_len;		}		if (gtk) {			if (sm->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;		wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",				buf, key_data_len);		if (version == 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,			       wpa_auth->Counter + WPA_NONCE_LEN - 16, 16);			inc_byte_array(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) {			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,					"PTK not valid when sending EAPOL-Key "					"frame");			free(hdr);			return;		}		wpa_calc_eapol_key_mic(version,				       sm->PTK.mic_key, (u8 *) hdr, len,				       key->key_mic);	}	wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx,			   1);	wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len,			    sm->pairwise_set);	free(hdr);}static void wpa_send_eapol(struct wpa_authenticator *wpa_auth,			   struct wpa_state_machine *sm,			   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){	int timeout_ms;	if (sm == NULL)		return;	__wpa_send_eapol(wpa_auth, sm, secure, mic, ack, install, pairwise,			 key_rsc, nonce, ie, ie_len, gtk, gtk_len, keyidx,			 gtk ? 1 : 0, 0);	timeout_ms = pairwise ? dot11RSNAConfigPairwiseUpdateTimeOut :		dot11RSNAConfigGroupUpdateTimeOut;	eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000,			       wpa_send_eapol_timeout, wpa_auth, sm);}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_auth_sm_event(struct wpa_state_machine *sm, wpa_event event){	if (sm == NULL)		return;	wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,			 "event %d notification", event);	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;		break;	}	sm->PTK_valid = FALSE;	memset(&sm->PTK, 0, sizeof(sm->PTK));	if (event != WPA_REAUTH_EAPOL) {		sm->pairwise_set = FALSE;		wpa_auth_set_key(sm->wpa_auth, "none", sm->addr, 0,				 (u8 *) "", 0);	}	wpa_sm_step(sm);}static const char * wpa_alg_txt(int alg){	switch (alg) {	case WPA_CIPHER_CCMP:		return "CCMP";	case WPA_CIPHER_TKIP:		return "TKIP";	case WPA_CIPHER_WEP104:	case WPA_CIPHER_WEP40:		return "WEP";	default:		return "";	}}SM_STATE(WPA_PTK, INITIALIZE){	SM_ENTRY_MA(WPA_PTK, INITIALIZE, wpa_ptk);	if (sm->Init) {		/* Init flag is not cleared here, so avoid busy		 * loop by claiming nothing changed. */		sm->changed = FALSE;	}	sm->keycount = 0;	if (sm->GUpdateStationKeys)		sm->wpa_auth->GKeyDoneStations--;	sm->GUpdateStationKeys = FALSE;	if (sm->wpa == WPA_VERSION_WPA)		sm->PInitAKeys = FALSE;	if (1 /* Unicast cipher supported AND (ESS OR ((IBSS or WDS) and	       * Local AA > Remote AA)) */) {		sm->Pair = TRUE;	}	wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 0);	wpa_auth_set_key(sm->wpa_auth, "none", sm->addr, 0, (u8 *) "", 0);	sm->pairwise_set = FALSE;	sm->PTK_valid = FALSE;	memset(&sm->PTK, 0, sizeof(sm->PTK));	wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0);	sm->TimeoutCtr = 0;	if (sm->wpa_key_mgmt == WPA_KEY_MGMT_PSK) {		wpa_auth_set_eapol(sm->wpa_auth, sm->addr,				   WPA_EAPOL_authorized, 0);	}}SM_STATE(WPA_PTK, DISCONNECT){	SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk);	sm->Disconnect = FALSE;	wpa_sta_disconnect(sm->wpa_auth, sm->addr);}SM_STATE(WPA_PTK, DISCONNECTED){	SM_ENTRY_MA(WPA_PTK, DISCONNECTED, wpa_ptk);	sm->wpa_auth->GNoStations--;	sm->DeauthenticationRequest = FALSE;}SM_STATE(WPA_PTK, AUTHENTICATION){	SM_ENTRY_MA(WPA_PTK, AUTHENTICATION, wpa_ptk);	sm->wpa_auth->GNoStations++;	memset(&sm->PTK, 0, sizeof(sm->PTK));	sm->PTK_valid = FALSE;	wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portControl_Auto,			   1);	wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 1);	sm->AuthenticationRequest = FALSE;}SM_STATE(WPA_PTK, AUTHENTICATION2){	SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk);	memcpy(sm->ANonce, sm->wpa_auth->Counter, WPA_NONCE_LEN);	inc_byte_array(sm->wpa_auth->Counter, WPA_NONCE_LEN);	sm->ReAuthenticationRequest = FALSE;	/* IEEE 802.11i does not clear TimeoutCtr here, but this is more	 * logical place than INITIALIZE since AUTHENTICATION2 can be	 * re-entered on ReAuthenticationRequest without going through	 * INITIALIZE. */	sm->TimeoutCtr = 0;}SM_STATE(WPA_PTK, INITPMK){	size_t len = WPA_PMK_LEN;	SM_ENTRY_MA(WPA_PTK, INITPMK, wpa_ptk);	if (sm->pmksa) {		wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache");		memcpy(sm->PMK, sm->pmksa->pmk, WPA_PMK_LEN);	} else if (wpa_auth_get_pmk(sm->wpa_auth, sm->addr, sm->PMK, &len) ==		   0) {		wpa_printf(MSG_DEBUG, "WPA: PMK from EAPOL state machine "			   "(len=%lu)", (unsigned long) len);	} else {		wpa_printf(MSG_DEBUG, "WPA: Could not get PMK");	}	sm->req_replay_counter_used = 0;	/* IEEE 802.11i does not set keyRun to FALSE, but not doing this	 * will break reauthentication since EAPOL state machines may not be	 * get into AUTHENTICATING state that clears keyRun before WPA state	 * machine enters AUTHENTICATION2 state and goes immediately to INITPMK	 * state and takes PMK from the previously used AAA Key. This will	 * eventually fail in 4-Way Handshake because Supplicant uses PMK	 * derived from the new AAA Key. Setting keyRun = FALSE here seems to	 * be good workaround for this issue. */	wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun, 0);}SM_STATE(WPA_PTK, INITPSK){	const u8 *psk;	SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk);	psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, NULL);	if (psk)		memcpy(sm->PMK, psk, WPA_PMK_LEN);	sm->req_replay_counter_used = 0;}SM_STATE(WPA_PTK, PTKSTART){	u8 *pmkid = NULL;	size_t pmkid_len = 0;	SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk);	sm->PTKRequest = FALSE;	sm->TimeoutEvt = FALSE;	wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,			"sending 1/4 msg of 4-Way Handshake");	if (sm->pmksa &&	    (pmkid = malloc(2 + RSN_SELECTOR_LEN + PMKID_LEN))) {		pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;		pmkid[0] = WLAN_EID_GENERIC;		pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN;		memcpy(&pmkid[2], RSN_KEY_DATA_PMKID, RSN_SELECTOR_LEN);		memcpy(&pmkid[2 + RSN_SELECTOR_LEN], sm->pmksa->pmkid,		       PMKID_LEN);	}	wpa_send_eapol(sm->wpa_auth, sm, 0, 0, 1, 0, 1, NULL, sm->ANonce,		       pmkid, pmkid_len, NULL, 0, 0);	free(pmkid);	sm->TimeoutCtr++;}SM_STATE(WPA_PTK, PTKCALCNEGOTIATING){	struct wpa_ptk PTK;	int ok = 0;	const u8 *pmk = NULL;	SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);	sm->EAPOLKeyReceived = FALSE;	/* WPA with IEEE 802.1X: use the derived PMK from EAP	 * WPA-PSK: iterate through possible PSKs and select the one matching	 * the packet */	for (;;) {		if (sm->wpa_key_mgmt == WPA_KEY_MGMT_PSK) {			pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, pmk);			if (pmk == NULL)				break;		} else			pmk = sm->PMK;		wpa_pmk_to_ptk(pmk, sm->wpa_auth->addr, sm->addr,			       sm->ANonce, sm->SNonce,			       (u8 *) &PTK, sizeof(PTK));		if (wpa_verify_key_mic(&PTK, sm->last_rx_eapol_key,				       sm->last_rx_eapol_key_len) == 0) {			ok = 1;			break;		}		if (sm->wpa_key_mgmt != WPA_KEY_MGMT_PSK)			break;	}	if (!ok) {		wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,				"invalid MIC in msg 2/4 of 4-Way Handshake");		return;	}	eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm);	if (sm->wpa_key_mgmt == WPA_KEY_MGMT_PSK) {		/* PSK may have changed from the previous choice, so update		 * state machine data based on whatever PSK was selected here.		 */		memcpy(sm->PMK, pmk, WPA_PMK_LEN);	}	sm->MICVerified = TRUE;	memcpy(&sm->PTK, &PTK, sizeof(PTK));	sm->PTK_valid = TRUE;}SM_STATE(WPA_PTK, PTKCALCNEGOTIATING2){	SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING2, wpa_ptk);	sm->TimeoutCt

⌨️ 快捷键说明

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