When the 4-Way Handshake is done eapol.c calls netdev_set_tk, then
optionally netdev_set_gtk and netdev_set_igtk. To support the no group
key option send the final SET STATION enabling the controlled port
inside the callback for the netdev_set_tk operation which always means
the end of a 4-Way Handshake rather than in the netdev_set_gtk callback.
The spec says exactly that the controlled port is enabled at the end of
the 4-Way Handshake.
The netlink operations will still be queued in the same order because
the netdev_set_tk/netdev_set_gtk/netdev_set_igtk calls happen in one
main loop iteration but even if the order changed it wouldn't matter.
On failure of any of the three operations netdev_setting_keys_failed
gets called and the remaining operations are cancelled.
Track the contents and size of the GTK and IGTK and if the Authenticator
(or an adversary) tries to set the same GTK/IGTK, process the packet
normally but do not resubmit the GTK/IGTK to the kernel.
GTK KDE was being checked for being a minimum of 6 bytes. Not quite
sure why since the minimum GTK key length is 16 bytes for CCMP.
Similarly make sure that the maximum length is not more than 32, which
is currently the largest key size (TKIP)
This is a bizarre case since MIC calculation succeeded for the incoming
packet. But just in case MIC calculation fails for the outgoing packet,
kill the handshake.
For testing purposes, it is useful to run hlrauc.py by itself
not including it from another python script like autotests do.
Better error checking was also added as testing can result in
badly formatted data.
The comments quoted sections of the specification that indicated STA
behavior for verifying Message 3 of 4 or GTK 1 of 2. But in reality the
code directly below simply calculated the MIC for Message 4 of 4 or GTK
2 of 2.
Use eapol_frame_watch_add/eapol_frame_watch_remove in eapol_sm, while
there simplify the early_frame logic and confirm sender address for
received frames.
We need to reset self._exception after _wait_for_async_op raises an
exception, otherwise _wait_for_async_op will report that exception for
every future operation (this wasn't an issue when an exception always
meant that the test was failing and objects were torn down anyway)
Set all the new field values into struct sta_state only after all the
error checks for better readabilty and fixing a possible issue if we
did "sta->rates = rates" and then detected en error and freed "rates".
Also update a comment which I think used the wording from 802.11-2012
instead of 802.11-2016.
DEL_KEY is not needed and will return errors right after NEW_STATION or
right after DEL_STATION. In both cases the kernel makes sure there are
no old keys for the station already.
As a temporary DBus API to switch between Station and Access Point
modes, add two methods on the Device interface. Add a new state
DEVICE_STATE_ACCESS_POINT which is in effect from the moment
StartAccessPoint is received (even before it returns) until
StopAccessPoint returns, there are no intermediate states when the
methods run for simplicity. Add checks across device.c to make sure
Station related functionality is disabled when in Access Point mode.
Add a utility to append a KDE to the key_data field in an EAPoL frame.
The KDE types enum is actually added to handshake.h because we've got
the utilities for finding those KDEs in a buffer there. The new
function is specific to EAPoL-Key frames though and perhaps to simple to
be split across handshake.c and eapol.c. Also it didn't seem useful to
use the ie_tlv_builder here.
Parse Association Request frames and send Association Responses, handle
Disassociation. With this we should be able to receive uncontrolled
port data frames since we register the STAs with the kernel.
In this version I don't register for Reassociation frames.