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

📄 wpa.c

📁 WPA在Linux下实现的原代码 WPA在Linux下实现的原代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			return -1;		}		ok = 1;	}	if (!ok) {		wpa_printf(MSG_WARNING, "WPA: Could not verify EAPOL-Key MIC "			   "- dropping packet");		return -1;	}	memcpy(sm->rx_replay_counter, key->replay_counter,	       WPA_REPLAY_COUNTER_LEN);	sm->rx_replay_counter_set = 1;	return 0;}/* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,					   struct wpa_eapol_key *key, u16 ver){	u16 keydatalen = WPA_GET_BE16(key->key_data_length);	wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data",		    (u8 *) (key + 1), keydatalen);	if (!sm->ptk_set) {		wpa_printf(MSG_WARNING, "WPA: PTK not available, "			   "cannot decrypt EAPOL-Key key data.");		return -1;	}	/* Decrypt key data here so that this operation does not need	 * to be implemented separately for each message type. */	if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) {		u8 ek[32];		memcpy(ek, key->key_iv, 16);		memcpy(ek + 16, sm->ptk.kek, 16);		rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen);	} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {		u8 *buf;		if (keydatalen % 8) {			wpa_printf(MSG_WARNING, "WPA: Unsupported "				   "AES-WRAP len %d", keydatalen);			return -1;		}		keydatalen -= 8; /* AES-WRAP adds 8 bytes */		buf = malloc(keydatalen);		if (buf == NULL) {			wpa_printf(MSG_WARNING, "WPA: No memory for "				   "AES-UNWRAP buffer");			return -1;		}		if (aes_unwrap(sm->ptk.kek, keydatalen / 8,			       (u8 *) (key + 1), buf)) {			free(buf);			wpa_printf(MSG_WARNING, "WPA: AES unwrap failed - "				   "could not decrypt EAPOL-Key key data");			return -1;		}		memcpy(key + 1, buf, keydatalen);		free(buf);		WPA_PUT_BE16(key->key_data_length, keydatalen);	}	wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data",			(u8 *) (key + 1), keydatalen);	return 0;}/** * wpa_sm_aborted_cached - Notify WPA that PMKSA caching was aborted * @sm: Pointer to WPA state machine data from wpa_sm_init() */void wpa_sm_aborted_cached(struct wpa_sm *sm){	if (sm && sm->cur_pmksa) {		wpa_printf(MSG_DEBUG, "RSN: Cancelling PMKSA caching attempt");		sm->cur_pmksa = NULL;	}}static void wpa_eapol_key_dump(const struct wpa_eapol_key *key){#ifndef CONFIG_NO_STDOUT_DEBUG	u16 key_info = WPA_GET_BE16(key->key_info);	wpa_printf(MSG_DEBUG, "  EAPOL-Key type=%d", key->type);	wpa_printf(MSG_DEBUG, "  key_info 0x%x (ver=%d keyidx=%d rsvd=%d %s"		   "%s%s%s%s%s%s%s)",		   key_info, key_info & WPA_KEY_INFO_TYPE_MASK,		   (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>		   WPA_KEY_INFO_KEY_INDEX_SHIFT,		   (key_info & (BIT(13) | BIT(14) | BIT(15))) >> 13,		   key_info & WPA_KEY_INFO_KEY_TYPE ? "Pairwise" : "Group",		   key_info & WPA_KEY_INFO_INSTALL ? " Install" : "",		   key_info & WPA_KEY_INFO_ACK ? " Ack" : "",		   key_info & WPA_KEY_INFO_MIC ? " MIC" : "",		   key_info & WPA_KEY_INFO_SECURE ? " Secure" : "",		   key_info & WPA_KEY_INFO_ERROR ? " Error" : "",		   key_info & WPA_KEY_INFO_REQUEST ? " Request" : "",		   key_info & WPA_KEY_INFO_ENCR_KEY_DATA ? " Encr" : "");	wpa_printf(MSG_DEBUG, "  key_length=%u key_data_length=%u",		   WPA_GET_BE16(key->key_length),		   WPA_GET_BE16(key->key_data_length));	wpa_hexdump(MSG_DEBUG, "  replay_counter",		    key->replay_counter, WPA_REPLAY_COUNTER_LEN);	wpa_hexdump(MSG_DEBUG, "  key_nonce", key->key_nonce, WPA_NONCE_LEN);	wpa_hexdump(MSG_DEBUG, "  key_iv", key->key_iv, 16);	wpa_hexdump(MSG_DEBUG, "  key_rsc", key->key_rsc, 8);	wpa_hexdump(MSG_DEBUG, "  key_id (reserved)", key->key_id, 8);	wpa_hexdump(MSG_DEBUG, "  key_mic", key->key_mic, 16);#endif /* CONFIG_NO_STDOUT_DEBUG */}/** * wpa_sm_rx_eapol - Process received WPA EAPOL frames * @sm: Pointer to WPA state machine data from wpa_sm_init() * @src_addr: Source MAC address of the EAPOL packet * @buf: Pointer to the beginning of the EAPOL data (EAPOL header) * @len: Length of the EAPOL frame * Returns: 1 = WPA EAPOL-Key processed, 0 = not a WPA EAPOL-Key, -1 failure * * This function is called for each received EAPOL frame. Other than EAPOL-Key * frames can be skipped if filtering is done elsewhere. wpa_sm_rx_eapol() is * only processing WPA and WPA2 EAPOL-Key frames. * * The received EAPOL-Key packets are validated and valid packets are replied * to. In addition, key material (PTK, GTK) is configured at the end of a * successful key handshake. */int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,		    const u8 *buf, size_t len){	size_t plen, data_len, extra_len;	struct ieee802_1x_hdr *hdr;	struct wpa_eapol_key *key;	u16 key_info, ver;	u8 *tmp;	int ret = -1;	if (len < sizeof(*hdr) + sizeof(*key)) {		wpa_printf(MSG_DEBUG, "WPA: EAPOL frame too short to be a WPA "			   "EAPOL-Key (len %lu, expecting at least %lu)",			   (unsigned long) len,			   (unsigned long) sizeof(*hdr) + sizeof(*key));		return 0;	}	tmp = malloc(len);	if (tmp == NULL)		return -1;	memcpy(tmp, buf, len);	hdr = (struct ieee802_1x_hdr *) tmp;	key = (struct wpa_eapol_key *) (hdr + 1);	plen = ntohs(hdr->length);	data_len = plen + sizeof(*hdr);	wpa_printf(MSG_DEBUG, "IEEE 802.1X RX: version=%d type=%d length=%lu",		   hdr->version, hdr->type, (unsigned long) plen);	if (hdr->version < EAPOL_VERSION) {		/* TODO: backwards compatibility */	}	if (hdr->type != IEEE802_1X_TYPE_EAPOL_KEY) {		wpa_printf(MSG_DEBUG, "WPA: EAPOL frame (type %u) discarded, "			"not a Key frame", hdr->type);		ret = 0;		goto out;	}	if (plen > len - sizeof(*hdr) || plen < sizeof(*key)) {		wpa_printf(MSG_DEBUG, "WPA: EAPOL frame payload size %lu "			   "invalid (frame size %lu)",			   (unsigned long) plen, (unsigned long) len);		ret = 0;		goto out;	}	if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN)	{		wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key type (%d) unknown, "			   "discarded", key->type);		ret = 0;		goto out;	}	wpa_eapol_key_dump(key);	eapol_sm_notify_lower_layer_success(sm->eapol);	wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-Key", tmp, len);	if (data_len < len) {		wpa_printf(MSG_DEBUG, "WPA: ignoring %lu bytes after the IEEE "			   "802.1X data", (unsigned long) len - data_len);	}	key_info = WPA_GET_BE16(key->key_info);	ver = key_info & WPA_KEY_INFO_TYPE_MASK;	if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&	    ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {		wpa_printf(MSG_INFO, "WPA: Unsupported EAPOL-Key descriptor "			   "version %d.", ver);		goto out;	}	if (sm->pairwise_cipher == WPA_CIPHER_CCMP &&	    ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {		wpa_printf(MSG_INFO, "WPA: CCMP is used, but EAPOL-Key "			   "descriptor version (%d) is not 2.", ver);		if (sm->group_cipher != WPA_CIPHER_CCMP &&		    !(key_info & WPA_KEY_INFO_KEY_TYPE)) {			/* Earlier versions of IEEE 802.11i did not explicitly			 * require version 2 descriptor for all EAPOL-Key			 * packets, so allow group keys to use version 1 if			 * CCMP is not used for them. */			wpa_printf(MSG_INFO, "WPA: Backwards compatibility: "				   "allow invalid version for non-CCMP group "				   "keys");		} else			goto out;	}	if (sm->rx_replay_counter_set &&	    memcmp(key->replay_counter, sm->rx_replay_counter,		   WPA_REPLAY_COUNTER_LEN) <= 0) {		wpa_printf(MSG_WARNING, "WPA: EAPOL-Key Replay Counter did not"			   " increase - dropping packet");		goto out;	}	if (!(key_info & WPA_KEY_INFO_ACK)) {		wpa_printf(MSG_INFO, "WPA: No Ack bit in key_info");		goto out;	}	if (key_info & WPA_KEY_INFO_REQUEST) {		wpa_printf(MSG_INFO, "WPA: EAPOL-Key with Request bit - "			   "dropped");		goto out;	}	if ((key_info & WPA_KEY_INFO_MIC) &&	    wpa_supplicant_verify_eapol_key_mic(sm, key, ver, tmp, data_len))		goto out;	extra_len = data_len - sizeof(*hdr) - sizeof(*key);	if (WPA_GET_BE16(key->key_data_length) > extra_len) {		wpa_msg(sm->ctx->ctx, MSG_INFO, "WPA: Invalid EAPOL-Key "			"frame - key_data overflow (%d > %lu)",			WPA_GET_BE16(key->key_data_length),			(unsigned long) extra_len);		goto out;	}	if (sm->proto == WPA_PROTO_RSN &&	    (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) &&	    wpa_supplicant_decrypt_key_data(sm, key, ver))		goto out;	if (key_info & WPA_KEY_INFO_KEY_TYPE) {		if (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) {			wpa_printf(MSG_WARNING, "WPA: Ignored EAPOL-Key "				   "(Pairwise) with non-zero key index");			goto out;		}		if (key_info & WPA_KEY_INFO_MIC) {			/* 3/4 4-Way Handshake */			wpa_supplicant_process_3_of_4(sm, key, extra_len, ver);		} else {			/* 1/4 4-Way Handshake */			wpa_supplicant_process_1_of_4(sm, src_addr, key,						      ver);		}	} else {		if (key_info & WPA_KEY_INFO_MIC) {			/* 1/2 Group Key Handshake */			wpa_supplicant_process_1_of_2(sm, src_addr, key,						      extra_len, ver);		} else {			wpa_printf(MSG_WARNING, "WPA: EAPOL-Key (Group) "				   "without Mic bit - dropped");		}	}	ret = 1;out:	free(tmp);	return ret;}static int wpa_cipher_bits(int cipher){	switch (cipher) {	case WPA_CIPHER_CCMP:		return 128;	case WPA_CIPHER_TKIP:		return 256;	case WPA_CIPHER_WEP104:		return 104;	case WPA_CIPHER_WEP40:		return 40;	default:		return 0;	}}static const u8 * wpa_key_mgmt_suite(struct wpa_sm *sm){	static const u8 *dummy = (u8 *) "\x00\x00\x00\x00";	switch (sm->key_mgmt) {	case WPA_KEY_MGMT_IEEE8021X:		return (sm->proto == WPA_PROTO_RSN ?			RSN_AUTH_KEY_MGMT_UNSPEC_802_1X :			WPA_AUTH_KEY_MGMT_UNSPEC_802_1X);	case WPA_KEY_MGMT_PSK:		return (sm->proto == WPA_PROTO_RSN ?			RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X :			WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X);	case WPA_KEY_MGMT_WPA_NONE:		return WPA_AUTH_KEY_MGMT_NONE;	default:		return dummy;	}}static const u8 * wpa_cipher_suite(struct wpa_sm *sm, int cipher){	static const u8 *dummy = (u8 *) "\x00\x00\x00\x00";	switch (cipher) {	case WPA_CIPHER_CCMP:		return (sm->proto == WPA_PROTO_RSN ?			RSN_CIPHER_SUITE_CCMP : WPA_CIPHER_SUITE_CCMP);	case WPA_CIPHER_TKIP:		return (sm->proto == WPA_PROTO_RSN ?			RSN_CIPHER_SUITE_TKIP : WPA_CIPHER_SUITE_TKIP);	case WPA_CIPHER_WEP104:		return (sm->proto == WPA_PROTO_RSN ?			RSN_CIPHER_SUITE_WEP104 : WPA_CIPHER_SUITE_WEP104);	case WPA_CIPHER_WEP40:		return (sm->proto == WPA_PROTO_RSN ?			RSN_CIPHER_SUITE_WEP40 : WPA_CIPHER_SUITE_WEP40);	case WPA_CIPHER_NONE:		return (sm->proto == WPA_PROTO_RSN ?			RSN_CIPHER_SUITE_NONE : WPA_CIPHER_SUITE_NONE);	default:		return dummy;	}}#define RSN_SUITE "%02x-%02x-%02x-%d"#define RSN_SUITE_ARG(s) (s)[0], (s)[1], (s)[2], (s)[3]/** * wpa_sm_get_mib - Dump text list of MIB entries * @sm: Pointer to WPA state machine data from wpa_sm_init() * @buf: Buffer for the list * @buflen: Length of the buffer * Returns: Number of bytes written to buffer * * This function is used fetch dot11 MIB variables. */int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen){	int len, i;	char pmkid_txt[PMKID_LEN * 2 + 1];	int rsna;	if (sm->cur_pmksa) {		char *pos = pmkid_txt;		for (i = 0; i < PMKID_LEN; i++) {			pos += sprintf(pos, "%02x", sm->cur_pmksa->pmkid[i]);		}	} else		pmkid_txt[0] = '\0';	if ((sm->key_mgmt == WPA_KEY_MGMT_PSK ||	     sm->key_mgmt == WPA_KEY_MGMT_IEEE8021X) &&	    sm->proto == WPA_PROTO_RSN)		rsna = 1;	else		rsna = 0;	len = snprintf(buf, buflen,		       "dot11RSNAOptionImplemented=TRUE\n"		       "dot11RSNAPreauthenticationImplemented=TRUE\n"		       "dot11RSNAEnabled=%s\n"		       "dot11RSNAPreauthenticationEnabled=%s\n"		       "dot11RSNAConfigVersion=%d\n"		       "dot11RSNAConfigPairwiseKeysSupported=5\n"		       "dot11RSNAConfigGroupCipherSize=%d\n"		       "dot11RSNAConfigPMKLifetime=%d\n"		       "dot11RSNAConfigPMKReauthThreshold=%d\n"		       "dot11RSNAConfigNumberOfPTKSAReplayCounters=1\n"		       "dot11RSNAConfigSATimeout=%d\n"		       "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n"		       "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n"		       "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n"		       "dot11RSNAPMKIDUsed=%s\n"		       "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n"		       "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n"		       "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n"		       "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n"		       "dot11RSNA4WayHandshakeFailures=%u\n",		       rsna ? "TRUE" : "FALSE",		       rsna ? "TRUE" : "FALSE",		       RSN_VERSION,		       wpa_cipher_bits(sm->group_cipher),		       sm->dot11RSNAConfigPMKLifetime,		       sm->dot11RSNAConfigPMKReauthThreshold,		       sm->dot11RSNAConfigSATimeout,		       RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)),		       RSN_SUITE_ARG(wpa_cipher_suite(sm,						      sm->pairwise_cipher)),		       RSN_SUITE_ARG(wpa_cipher_suite(sm, sm->group_cipher)),		       pmkid_txt,		       RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)),		       RSN_SUITE_ARG(wpa_cipher_suite(sm,						      sm->pairwise_cipher)),		       RSN_SUITE_ARG(wpa_cipher_suite(sm, sm->group_cipher)),		       sm->dot11RSNA4WayHandshakeFailures);	return len;}/** * wpa_sm_init - Initialize WPA state machine * @ctx: Context pointer for callbacks; this needs to be an allocated buffer * Returns: Pointer to the allocated WPA state machine data * * This function is used to allocate a new WPA state machine and the returned * value is passed to all WPA state machine calls. */struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx){	struct wpa_sm *sm;	sm = malloc(sizeof(*sm));	if (sm == NULL)		return NULL;	memset(sm, 0, sizeof(*sm));	sm->renew_snonce = 1;	sm->ctx = ctx;	sm->dot11RSNAConfigPMKLifetime = 43200;	sm->dot11RSNAConfigPMKReauthThreshold = 70;	sm->dot11RSNAConfigSATimeout = 60;	return sm;}/** * wpa_sm_deinit - Deinitialize WPA state machine * @sm: Pointer to WPA state machine 

⌨️ 快捷键说明

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