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.
The MIC length was hard coded to 16 bytes everywhere, and since several
AKMs require larger MIC's (24/32) this needed to change. The main issue
was that the MIC was hard coded to 16 bytes inside eapol_key. Instead
of doing this, the MIC, key_data_length, and key_data elements were all
bundled into key_data[0]. In order to retrieve the MIC, key_data_len,
or key_data several macros were introduced which account for the MIC
length provided.
A consequence of this is that all the verify functions inside eapol now
require the MIC length as a parameter because without it they cannot
determine the byte offset of key_data or key_data_length.
The MIC length for a given handshake is set inside the SM when starting
EAPoL. This length is determined by the AKM for the handshake.
Fixes:
CC monitor/pcap.o
monitor/pcap.c: In function ‘pcap_create’:
monitor/pcap.c:121:6: error: ‘S_IRUSR’ undeclared (first use in this function)
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
^
monitor/pcap.c:121:6: note: each undeclared identifier is reported only once for each function it appears in
monitor/pcap.c:121:16: error: ‘S_IWUSR’ undeclared (first use in this function)
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
^
monitor/pcap.c:121:26: error: ‘S_IRGRP’ undeclared (first use in this function)
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
^
monitor/pcap.c:121:36: error: ‘S_IROTH’ undeclared (first use in this function)
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
^
==24195== Syscall param socketcall.sendto(msg) points to uninitialised byte(s)
==24195== at 0x4F3DBEF: sendto (in /lib64/libc-2.26.so)
==24195== by 0x13A453: can_write_data (netlink.c:119)
==24195== by 0x13866B: io_callback (io.c:149)
==24195== by 0x137365: l_main_iterate (main.c:389)
==24195== by 0x1374A3: l_main_run (main.c:436)
==24195== by 0x113524: main (main.c:832)
==24195== Address 0x5205f99 is 57 bytes inside a block of size 88 alloc'd
==24195== at 0x4C2D0AF: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==24195== by 0x133931: l_malloc (util.c:62)
==24195== by 0x13AEF3: l_netlink_send (netlink.c:411)
==24195== by 0x112351: rtm_interface_send_message (main.c:276)
==24195== by 0x1126F3: iwmon_interface_lookup (main.c:405)
==24195== by 0x11351F: main (main.c:830)
==24195== Uninitialised value was created by a heap allocation
==24195== at 0x4C2D0AF: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==24195== by 0x133931: l_malloc (util.c:62)
==24195== by 0x11217B: rtm_interface_send_message (main.c:234)
==24195== by 0x1126F3: iwmon_interface_lookup (main.c:405)
==24195== by 0x11351F: main (main.c:830)
==23290== Invalid read of size 4
==23290== at 0x12D334: timeout_destroy (timeout.c:61)
==23290== by 0x12CDD1: l_main_exit (main.c:466)
==23290== by 0x111F3B: main (main.c:835)
==23290== Address 0x5211d80 is 0 bytes inside a block of size 32 free'd
==23290== at 0x4C2E1BB: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==23290== by 0x111F36: main (main.c:833)
==23290== Block was alloc'd at
==23290== at 0x4C2CF8F: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==23290== by 0x12A74D: l_malloc (util.c:62)
==23290== by 0x12D40F: timeout_create_with_nanoseconds (timeout.c:135)
==23290== by 0x112A31: signal_handler (main.c:661)
==23290== by 0x12D03A: signal_callback (signal.c:82)
==23290== by 0x12CC6D: l_main_iterate (main.c:387)
==23290== by 0x12CD3B: l_main_run (main.c:434)
==23290== by 0x1121F2: main (main.c:821)
==23290==
==23290== Invalid read of size 8
==23290== at 0x12D33B: timeout_destroy (timeout.c:64)
==23290== by 0x12CDD1: l_main_exit (main.c:466)
==23290== by 0x111F3B: main (main.c:835)
==23290== Address 0x5211d90 is 16 bytes inside a block of size 32 free'd
==23290== at 0x4C2E1BB: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==23290== by 0x111F36: main (main.c:833)
==23290== Block was alloc'd at
==23290== at 0x4C2CF8F: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==23290== by 0x12A74D: l_malloc (util.c:62)
==23290== by 0x12D40F: timeout_create_with_nanoseconds (timeout.c:135)
==23290== by 0x112A31: signal_handler (main.c:661)
==23290== by 0x12D03A: signal_callback (signal.c:82)
==23290== by 0x12CC6D: l_main_iterate (main.c:387)
==23290== by 0x12CD3B: l_main_run (main.c:434)
==23290== by 0x1121F2: main (main.c:821)
==23290==
==23290== Invalid write of size 4
==23290== at 0x12D33F: timeout_destroy (timeout.c:62)
==23290== by 0x12CDD1: l_main_exit (main.c:466)
==23290== by 0x111F3B: main (main.c:835)
==23290== Address 0x5211d80 is 0 bytes inside a block of size 32 free'd
==23290== at 0x4C2E1BB: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==23290== by 0x111F36: main (main.c:833)
==23290== Block was alloc'd at
==23290== at 0x4C2CF8F: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==23290== by 0x12A74D: l_malloc (util.c:62)
==23290== by 0x12D40F: timeout_create_with_nanoseconds (timeout.c:135)
==23290== by 0x112A31: signal_handler (main.c:661)
==23290== by 0x12D03A: signal_callback (signal.c:82)
==23290== by 0x12CC6D: l_main_iterate (main.c:387)
==23290== by 0x12CD3B: l_main_run (main.c:434)
==23290== by 0x1121F2: main (main.c:821)
to fix compilation against MUSL libc.
The struct ethhdr does exists in netinet/if_ether.h and linux/if_ether.h
so including the linux headers after the libc headers lets libc_compat.h
work as intended.
The subtype was only printed if mpdu_validate had returned an error for
the frame, i.e. would not be printed for well formed frames. This was
probably an intent to avoid printing the frame subtype after all the
conents of the body frame had been printed already, but iwmon only
supports printing of Authentication and Deauthentication frames so far.
Kernel v4.10 and later no longer export GENL_ID_GENERATE (which was
defined as 0). iwd was using this symbol to check for unmodified local
values rather than to ask for a dynamically generated netlink ID anyway,
so it makes sense to use the value 0 directly. This will work with
kernels before and after the GENL_ID_GENERATE change.