mirror of
				https://git.kernel.org/pub/scm/network/wireless/iwd.git
				synced 2025-10-31 04:57:25 +01:00 
			
		
		
		
	ie: Parse vendor specific IE
Currently it supports Microsoft vendor specific information element with version and type value 1 only. Typically it contains WPA security related information.
This commit is contained in:
		
							parent
							
								
									7eac75fa69
								
							
						
					
					
						commit
						50c7346d19
					
				
							
								
								
									
										240
									
								
								src/ie.c
									
									
									
									
									
								
							
							
						
						
									
										240
									
								
								src/ie.c
									
									
									
									
									
								
							| @ -31,6 +31,7 @@ | ||||
| #include "ie.h" | ||||
| 
 | ||||
| static const uint8_t ieee_oui[3] = { 0x00, 0x0f, 0xac }; | ||||
| static const uint8_t microsoft_oui[3] = { 0x00, 0x50, 0xf2 }; | ||||
| 
 | ||||
| void ie_tlv_iter_init(struct ie_tlv_iter *iter, const unsigned char *tlv, | ||||
| 			unsigned int len) | ||||
| @ -761,3 +762,242 @@ done: | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| /* 802.11i-2004, Section 7.3.2.25.1 and WPA_80211_v3_1 Section 2.1 */ | ||||
| static bool ie_parse_wpa_cipher_suite(const uint8_t *data, | ||||
| 					enum ie_rsn_cipher_suite *out) | ||||
| { | ||||
| 	/*
 | ||||
| 	 * Compare the OUI to the ones we know.  OUI Format is found in | ||||
| 	 * Figure 8-187 of 802.11 | ||||
| 	 */ | ||||
| 	if (!memcmp(data, microsoft_oui, 3)) { | ||||
| 		/* Suite type from 802.11i-2004, Table 20da */ | ||||
| 		switch (data[3]) { | ||||
| 		case 0: | ||||
| 			*out = IE_RSN_CIPHER_SUITE_USE_GROUP_CIPHER; | ||||
| 			return true; | ||||
| 		case 1: | ||||
| 			*out = IE_RSN_CIPHER_SUITE_WEP40; | ||||
| 			return true; | ||||
| 		case 2: | ||||
| 			*out = IE_RSN_CIPHER_SUITE_TKIP; | ||||
| 			return true; | ||||
| 		case 4: | ||||
| 			*out = IE_RSN_CIPHER_SUITE_CCMP; | ||||
| 			return true; | ||||
| 		case 5: | ||||
| 			*out = IE_RSN_CIPHER_SUITE_WEP104; | ||||
| 			return true; | ||||
| 		default: | ||||
| 			return false; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| /* 802.11i-2004, Section 7.3.2.25.2 and WPA_80211_v3_1 Section 2.1 */ | ||||
| static bool ie_parse_wpa_akm_suite(const uint8_t *data, | ||||
| 					enum ie_rsn_akm_suite *out) | ||||
| { | ||||
| 	/*
 | ||||
| 	 * Compare the OUI to the ones we know.  OUI Format is found in | ||||
| 	 * Figure 8-187 of 802.11 | ||||
| 	 */ | ||||
| 	if (!memcmp(data, microsoft_oui, 3)) { | ||||
| 		/* Suite type from 802.11i-2004, Table 20dc */ | ||||
| 		switch (data[3]) { | ||||
| 		case 1: | ||||
| 			*out = IE_RSN_AKM_SUITE_8021X; | ||||
| 			return true; | ||||
| 		case 2: | ||||
| 			*out = IE_RSN_AKM_SUITE_PSK; | ||||
| 			return true; | ||||
| 		default: | ||||
| 			return false; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| static bool ie_parse_wpa_group_cipher(const uint8_t *data, | ||||
| 					enum ie_rsn_cipher_suite *out) | ||||
| { | ||||
| 	enum ie_rsn_cipher_suite tmp; | ||||
| 
 | ||||
| 	bool r = ie_parse_wpa_cipher_suite(data, &tmp); | ||||
| 
 | ||||
| 	if (!r) | ||||
| 		return r; | ||||
| 
 | ||||
| 	switch (tmp) { | ||||
| 	case IE_RSN_CIPHER_SUITE_CCMP: | ||||
| 	case IE_RSN_CIPHER_SUITE_TKIP: | ||||
| 	case IE_RSN_CIPHER_SUITE_WEP104: | ||||
| 	case IE_RSN_CIPHER_SUITE_WEP40: | ||||
| 		break; | ||||
| 	default: | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	*out = tmp; | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static bool ie_parse_wpa_pairwise_cipher(const uint8_t *data, | ||||
| 					enum ie_rsn_cipher_suite *out) | ||||
| { | ||||
| 	enum ie_rsn_cipher_suite tmp; | ||||
| 
 | ||||
| 	bool r = ie_parse_wpa_cipher_suite(data, &tmp); | ||||
| 
 | ||||
| 	if (!r) | ||||
| 		return r; | ||||
| 
 | ||||
| 	switch (tmp) { | ||||
| 	case IE_RSN_CIPHER_SUITE_CCMP: | ||||
| 	case IE_RSN_CIPHER_SUITE_TKIP: | ||||
| 	case IE_RSN_CIPHER_SUITE_WEP104: | ||||
| 	case IE_RSN_CIPHER_SUITE_WEP40: | ||||
| 	/* TODO : not sure about GROUP_CIPHER */ | ||||
| 		break; | ||||
| 	default: | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	*out = tmp; | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| bool is_ie_wpa_ie(const uint8_t *data, uint8_t len) | ||||
| { | ||||
| 	if (!data || len < 6) | ||||
| 		return false; | ||||
| 
 | ||||
| 	if ((!memcmp(data, microsoft_oui, 3) && data[3] == 1 && | ||||
| 						l_get_le16(data + 4) == 1)) | ||||
| 		return true; | ||||
| 
 | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| int ie_parse_wpa(struct ie_tlv_iter *iter, struct ie_rsn_info *out_info) | ||||
| { | ||||
| 	const uint8_t *data = iter->data; | ||||
| 	size_t len = iter->len; | ||||
| 	struct ie_rsn_info info; | ||||
| 	uint16_t count; | ||||
| 	uint16_t i; | ||||
| 
 | ||||
| 	if (!is_ie_wpa_ie(iter->data, iter->len)) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	info.group_cipher = IE_RSN_CIPHER_SUITE_TKIP; | ||||
| 	info.pairwise_ciphers = IE_RSN_CIPHER_SUITE_TKIP; | ||||
| 	info.akm_suites = IE_RSN_AKM_SUITE_PSK; | ||||
| 
 | ||||
| 	memset(&info, 0, sizeof(info)); | ||||
| 	RSNE_ADVANCE(data, len, 6); | ||||
| 
 | ||||
| 	/* Parse Group Cipher Suite field */ | ||||
| 	if (len < 4) | ||||
| 		return -EBADMSG; | ||||
| 
 | ||||
| 	if (!ie_parse_wpa_group_cipher(data, &info.group_cipher)) | ||||
| 		return -ERANGE; | ||||
| 
 | ||||
| 	RSNE_ADVANCE(data, len, 4); | ||||
| 
 | ||||
| 	/* Parse Pairwise Cipher Suite Count field */ | ||||
| 	if (len < 2) | ||||
| 		return -EBADMSG; | ||||
| 
 | ||||
| 	count = l_get_le16(data); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * The spec doesn't seem to explicitly say what to do in this case, | ||||
| 	 * so we assume this situation is invalid. | ||||
| 	 */ | ||||
| 	if (count == 0) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	data += 2; | ||||
| 	len -= 2; | ||||
| 
 | ||||
| 	if (len < 4 * count) | ||||
| 		return -EBADMSG; | ||||
| 
 | ||||
| 	/* Parse Pairwise Cipher Suite List field */ | ||||
| 	for (i = 0, info.pairwise_ciphers = 0; i < count; i++) { | ||||
| 		enum ie_rsn_cipher_suite suite; | ||||
| 
 | ||||
| 		if (!ie_parse_wpa_pairwise_cipher(data + i * 4, &suite)) | ||||
| 			return -ERANGE; | ||||
| 
 | ||||
| 		info.pairwise_ciphers |= suite; | ||||
| 	} | ||||
| 
 | ||||
| 	RSNE_ADVANCE(data, len, count * 4); | ||||
| 
 | ||||
| 	/* Parse AKM Suite Count field */ | ||||
| 	if (len < 2) | ||||
| 		return -EBADMSG; | ||||
| 
 | ||||
| 	count = l_get_le16(data); | ||||
| 	if (count == 0) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	data += 2; | ||||
| 	len -= 2; | ||||
| 
 | ||||
| 	if (len < 4 * count) | ||||
| 		return -EBADMSG; | ||||
| 
 | ||||
| 	/* Parse AKM Suite List field */ | ||||
| 	for (i = 0, info.akm_suites = 0; i < count; i++) { | ||||
| 		enum ie_rsn_akm_suite suite; | ||||
| 
 | ||||
| 		if (!ie_parse_wpa_akm_suite(data + i * 4, &suite)) | ||||
| 			return -ERANGE; | ||||
| 
 | ||||
| 		info.akm_suites |= suite; | ||||
| 	} | ||||
| 
 | ||||
| 	RSNE_ADVANCE(data, len, count * 4); | ||||
| 
 | ||||
| 	return -EBADMSG; | ||||
| 
 | ||||
| done: | ||||
| 	/*
 | ||||
| 	 * 802.11i, Section 7.3.2.25.1 | ||||
| 	 * Use of CCMP as the group cipher suite with TKIP as the | ||||
| 	 * pairwise cipher suite shall not be supported. | ||||
| 	 */ | ||||
| 
 | ||||
| 	if (info.group_cipher & IE_RSN_CIPHER_SUITE_CCMP && | ||||
| 			info.pairwise_ciphers & IE_RSN_CIPHER_SUITE_TKIP) | ||||
| 		return -EBADMSG; | ||||
| 
 | ||||
| 	if (out_info) | ||||
| 		memcpy(out_info, &info, sizeof(info)); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int ie_parse_wpa_from_data(const uint8_t *data, size_t len, | ||||
| 						struct ie_rsn_info *info) | ||||
| { | ||||
| 	struct ie_tlv_iter iter; | ||||
| 
 | ||||
| 	ie_tlv_iter_init(&iter, data, len); | ||||
| 
 | ||||
| 	if (!ie_tlv_iter_next(&iter)) | ||||
| 		return -EMSGSIZE; | ||||
| 
 | ||||
| 	if (ie_tlv_iter_get_tag(&iter) != IE_TYPE_VENDOR_SPECIFIC) | ||||
| 		return -EPROTOTYPE; | ||||
| 
 | ||||
| 	return ie_parse_wpa(&iter, info); | ||||
| } | ||||
|  | ||||
							
								
								
									
										5
									
								
								src/ie.h
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								src/ie.h
									
									
									
									
									
								
							| @ -264,3 +264,8 @@ int ie_parse_rsne(struct ie_tlv_iter *iter, struct ie_rsn_info *info); | ||||
| int ie_parse_rsne_from_data(const uint8_t *data, size_t len, | ||||
| 				struct ie_rsn_info *info); | ||||
| bool ie_build_rsne(const struct ie_rsn_info *info, uint8_t *to); | ||||
| 
 | ||||
| int ie_parse_wpa(struct ie_tlv_iter *iter, struct ie_rsn_info *out_info); | ||||
| int ie_parse_wpa_from_data(const uint8_t *data, size_t len, | ||||
| 						struct ie_rsn_info *info); | ||||
| bool is_ie_wpa_ie(const uint8_t *data, uint8_t len); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Ravi kumar Veeramally
						Ravi kumar Veeramally