monitor: allow monitor to support other MIC lengths

Unfortunately there is no way to determine the MIC length just from the
eapol frame. 802.11 defined AKMs define the MIC length, but non 802.11
AKMs (e.g. OWE) can define their own MIC length. For this reason it seem
infeasable to track these special AKM's data flow to determine the MIC
length.

To work around this we can just try different MIC lengths (since there
are only 3 after all). This allows us to get key data length and see if
the total packet size equals the frame length + key data length. If the
sizes don't match we can try the next MIC length.
This commit is contained in:
James Prestwood 2019-01-17 12:25:29 -08:00 committed by Denis Kenzior
parent 374b367ba4
commit 3b801526f0
1 changed files with 38 additions and 6 deletions

View File

@ -3839,8 +3839,36 @@ static void print_attributes(int indent, const struct attr_entry *table,
static void print_eapol_key(const void *data, uint32_t size)
{
const struct eapol_key *ek = eapol_key_validate(data, size, 16);
const struct eapol_key *ek = (struct eapol_key *)data;
size_t mic_lengths[] = { 16, 24, 32 };
size_t mic_len = 0;
int i;
/*
* The MIC length is not encoded anywhere in the frame, and should be
* determined by AKM. To even further complicate things, some non
* 802.11 AKMs define their own MIC lengths. But since the only valid
* lengths are 16, 24 and 32 its trivial to try each until we find a
* matching length.
*/
for (i = 0; i < 3; i++) {
size_t mlen = mic_lengths[i];
if (size < EAPOL_FRAME_LEN(mlen))
break;
if (size == EAPOL_FRAME_LEN(mlen) +
EAPOL_KEY_DATA_LEN(ek, mlen)) {
mic_len = mlen;
break;
}
}
/* could not determine MIC length, malformed packet? */
if (!mic_len)
return;
ek = eapol_key_validate(data, size, mic_len);
if (!ek)
return;
@ -3871,17 +3899,21 @@ static void print_eapol_key(const void *data, uint32_t size)
print_hexdump(2, ek->eapol_key_iv, 16);
print_attr(1, "Key RSC ");
print_hexdump(2, ek->key_rsc, 8);
print_attr(1, "Key MIC Data");
print_hexdump(2, EAPOL_KEY_MIC(ek), 16);
print_hexdump(2, EAPOL_KEY_MIC(ek), mic_len);
if (ek->encrypted_key_data) {
print_attr(1, "Key Data: len %d", EAPOL_KEY_DATA_LEN(ek, 16));
print_hexdump(2, EAPOL_KEY_DATA(ek, 16),
EAPOL_KEY_DATA_LEN(ek, 16));
print_attr(1, "Key Data: len %d",
EAPOL_KEY_DATA_LEN(ek, mic_len));
print_hexdump(2, EAPOL_KEY_DATA(ek, mic_len),
EAPOL_KEY_DATA_LEN(ek, mic_len));
return;
}
print_ie(1, "Key Data", ek->key_data, EAPOL_KEY_DATA_LEN(ek, 16));
print_ie(1, "Key Data", EAPOL_KEY_DATA(ek, mic_len),
EAPOL_KEY_DATA_LEN(ek, mic_len));
}
static void netlink_str(char *str, size_t size,