Don't start the handshake timeout in eapol_start if either
handshake->ptk_complete is set (handshake already done) or
handshake->have_snonce is set (steps 1&2 done). This accounts for
eapol_start being called after a Fast Transition when a 4-Way handshake
is not expected.
Split the igtk parameter to handshake_state_install_igtk into one
parameter for the actual IGTK buffer and one for the IPN buffer instead
of requiring the caller to have them both in one continuous buffer.
With FT protocol, one is received encrypted and the other in plain text.
Despite RFC3748 mandating MSKs to be at least 256 bits some EAP methods
return shorter MSKs. Since we call handshake_failed when the MSK is too
short, EAP methods have to be careful with their calls to set_key_material
because it may result in a call to the method's .remove method.
EAP-TLS and EAP-TTLS can't handle that currently and would be difficult to
adapt because of the TLS internals but they always set msk_len to 64 so
handshake_failed will not be called.
Make the use of EAPOL-Start the default and send it when configured for
8021x and either we receive no EAPOL-EAP from from the AP before
timeout, or if the AP tries to start a 4-Way Handshake.
On certain routers, the 4-Way handshake message 3 of 4 contains a key iv
field which is not zero as it is supposed to. This causes us to fail
the handshake.
Since the iv field is not utilized in this particular case, it is safe
to simply warn rather than fail the handshake outright.
Remove the keys and other data from struct eapol_sm, update device.c,
netdev.c and wsc.c to use the handshake_state object instead of
eapol_sm. This also gets rid of eapol_cancel and the ifindex parameter
in some of the eapol functions where sm->handshake->ifindex can be
used instead.
Add space in the eapol_sm struct for the pieces of information required
for the FT 4-Way Handshake and add setters for device.c and netdev.c to
be able to provide the data.
The len parameter was only used so it could be validated against ie[1],
but since it was not checked to be > 2, it must have been validated
already, the check was redundant. In any case all users directly
passed ie[1] as len anyway. This makes it consistent with the ie
parsers and builders which didn't require a length.
Split eapol_start into two calls, one to register the state machine so
that the PAE read handler knows not to discard frames for that ifindex,
and eapol_start to actually start processing the frames. This is needed
because, as per the comment in netdev.c, due to scheduling the PAE
socket read handler may trigger before the CMD_CONNECT event handler,
which needs to parse the FTE from the Associate Response frame and
supply it to the eapol SM before it can do anything with the message 1
of 4 of the FT handshake.
Another issue is that depending on the driver or timing, the underlying
link might not be marked as 'ready' by the kernel. In this case, our
response to Message 1 of the 4-way Handshake is written and accepted by
the kernel, but gets dropped on the floor internally. Which leads to
timeouts if the AP doesn't retransmit.
It doesn't matter for crypto_derive_pairwise_ptk in non-SHA256 mode
but in the FT PTK derivation function, as well as in SHA256 mode all
bytes of the output do actually change with the PTK size.
We used to open a socket for each wireless interface. This patch uses a
single socket with an attached BPF to handle all EAPoL traffic via a
single file descriptor.
Instead of one global protocol_version, we now store it inside eapol_sm.
This allows us to use the same protocol version for our response as the
request from the authenticator.
For unit tests where we had protocol version mismatches, a new method is
introduced to explicitly set the protocol version to use.
Instead of passing the user_data parameter in every __eapol_rx_packet
call to be used by EAPOL in all tx_packet calls, add
eapol_sm_set_tx_user_data function that sets the value of user_data for
all subsequent tx_packet calls. This way tx_packet can be called from
places that are not necessarily inside an __eapol_rx_packet call.
Instead of passing in the RSN/WPA elements, simply pass in the
configured cipher. This will make the implementation of the install_gtk
callback much simpler.
Step 4 is always sent without encrypted Key Data according to Section
11.6.6.5. In the case of WPA, Encrypted Key Data field is reserved, and
should always be 0. Thus it is safe to drop the !is_wpa condition.
We start a timer. This handles the case that the Authenticator does
not send us the first message of the 4-way handshake, or disappears
before sending us the 3rd message.