mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-22 14:49:24 +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;
|
*out = tmp;
|
||||||
return true;
|
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
|
* Information elements, IEEE Std 802.11 ch. 8.4.2
|
||||||
*/
|
*/
|
||||||
@ -199,6 +202,26 @@ struct ie_tlv_builder {
|
|||||||
unsigned int len;
|
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,
|
void ie_tlv_iter_init(struct ie_tlv_iter *iter, const unsigned char *tlv,
|
||||||
unsigned int len);
|
unsigned int len);
|
||||||
void ie_tlv_iter_recurse(struct ie_tlv_iter *iter,
|
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);
|
struct ie_tlv_builder *recurse);
|
||||||
void ie_tlv_builder_finalize(struct ie_tlv_builder *builder,
|
void ie_tlv_builder_finalize(struct ie_tlv_builder *builder,
|
||||||
unsigned int *out_len);
|
unsigned int *out_len);
|
||||||
|
|
||||||
|
int ie_parse_rsne(struct ie_tlv_iter *iter, struct ie_rsn_info *info);
|
||||||
|
Loading…
Reference in New Issue
Block a user