mirror of
				https://git.kernel.org/pub/scm/network/wireless/iwd.git
				synced 2025-10-30 20:37:26 +01:00 
			
		
		
		
	ie: Add initial parser for RSN Elements
As found in 802.11 Section 8.4.2.27. Currently the parser does not handle the Capabilities, Group Management Cipher Suite or PMKID related fields.
This commit is contained in:
		
							parent
							
								
									2b7432bddb
								
							
						
					
					
						commit
						2d8f1cca0b
					
				
							
								
								
									
										104
									
								
								src/ie.c
									
									
									
									
									
								
							
							
						
						
									
										104
									
								
								src/ie.c
									
									
									
									
									
								
							| @ -318,3 +318,107 @@ static bool ie_parse_pairwise_cipher(const uint8_t *data, | ||||
| 	*out = tmp; | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| #define RSNE_ADVANCE(data, len, step)	\ | ||||
| 	data += step;			\ | ||||
| 	len -= step;			\ | ||||
| 					\ | ||||
| 	if (len == 0)			\ | ||||
| 		goto done		\ | ||||
| 
 | ||||
| int ie_parse_rsne(struct ie_tlv_iter *iter, struct ie_rsn_info *out_info) | ||||
| { | ||||
| 	const uint8_t *data = iter->data; | ||||
| 	size_t len = iter->len; | ||||
| 	uint16_t version; | ||||
| 	struct ie_rsn_info info; | ||||
| 	uint16_t count; | ||||
| 	uint16_t i; | ||||
| 
 | ||||
| 	memset(&info, 0, sizeof(info)); | ||||
| 	info.group_cipher = IE_RSN_CIPHER_SUITE_CCMP; | ||||
| 	info.pairwise_ciphers = IE_RSN_CIPHER_SUITE_CCMP; | ||||
| 	info.akm_suites = IE_RSN_AKM_SUITE_8021X; | ||||
| 
 | ||||
| 	/* Parse Version field */ | ||||
| 	if (len < 2) | ||||
| 		return -EMSGSIZE; | ||||
| 
 | ||||
| 	version = l_get_le16(data); | ||||
| 	if (version != 0x01) | ||||
| 		return -EBADMSG; | ||||
| 
 | ||||
| 	RSNE_ADVANCE(data, len, 2); | ||||
| 
 | ||||
| 	/* Parse Group Cipher Suite field */ | ||||
| 	if (len < 4) | ||||
| 		return -EBADMSG; | ||||
| 
 | ||||
| 	if (!ie_parse_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_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_akm_suite(data + i * 4, &suite)) | ||||
| 			return -ERANGE; | ||||
| 
 | ||||
| 		info.akm_suites |= suite; | ||||
| 	} | ||||
| 
 | ||||
| 	RSNE_ADVANCE(data, len, count * 4); | ||||
| 
 | ||||
| done: | ||||
| 	if (out_info) | ||||
| 		memcpy(out_info, &info, sizeof(info)); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
							
								
								
									
										25
									
								
								src/ie.h
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								src/ie.h
									
									
									
									
									
								
							| @ -20,6 +20,9 @@ | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #include <stdbool.h> | ||||
| #include <stddef.h> | ||||
| 
 | ||||
| /*
 | ||||
|  * Information elements, IEEE Std 802.11 ch. 8.4.2 | ||||
|  */ | ||||
| @ -199,6 +202,26 @@ struct ie_tlv_builder { | ||||
| 	unsigned int len; | ||||
| }; | ||||
| 
 | ||||
| struct ie_rsn_info { | ||||
| 	enum ie_rsn_cipher_suite group_cipher; | ||||
| 	uint16_t pairwise_ciphers; | ||||
| 	uint16_t akm_suites; | ||||
| 	bool preauthentication:1; | ||||
| 	bool no_pairwise:1; | ||||
| 	uint8_t ptksa_replay_counter:2; | ||||
| 	uint8_t gtksa_replay_counter:2; | ||||
| 	bool mfpr:1; | ||||
| 	bool mfpc:1; | ||||
| 	bool peerkey_enabled:1; | ||||
| 	bool spp_a_msdu_capable:1; | ||||
| 	bool spp_a_msdu_required:1; | ||||
| 	bool pbac:1; | ||||
| 	bool extended_key_id:1; | ||||
| 	uint8_t num_pmkids; | ||||
| 	const uint8_t *pmkids; | ||||
| 	enum ie_rsn_cipher_suite group_management_cipher; | ||||
| }; | ||||
| 
 | ||||
| void ie_tlv_iter_init(struct ie_tlv_iter *iter, const unsigned char *tlv, | ||||
| 			unsigned int len); | ||||
| void ie_tlv_iter_recurse(struct ie_tlv_iter *iter, | ||||
| @ -214,3 +237,5 @@ bool ie_tlv_builder_recurse(struct ie_tlv_builder *builder, | ||||
| 			struct ie_tlv_builder *recurse); | ||||
| void ie_tlv_builder_finalize(struct ie_tlv_builder *builder, | ||||
| 			unsigned int *out_len); | ||||
| 
 | ||||
| int ie_parse_rsne(struct ie_tlv_iter *iter, struct ie_rsn_info *info); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Denis Kenzior
						Denis Kenzior