Remove an unneeded buffer and its memcpy, remove the now unneeded use of
l_checksum_digest_length and use l_checksum_reset instead of creating a
new l_checksum for each chunk.
ELL ECC supports group 20 (P384) so OWE can also support it. This also
adds group negotiation, where OWE can choose a different group than the
default if the AP requests it.
A check needed to be added in netdev in order for the negotiation to work.
The RFC says that if a group is not supported association should be rejected
with code 77 (unsupported finite cyclic group) and association should be
started again. This rejection was causing a connect event to be emitted by
the kernel (in addition to an associate event) which would result in netdev
terminating the connection, which we didn't want. Since OWE receives the
rejected associate event it can intelligently decide whether it really wants
to terminate (out of supported groups) or try the next available group.
This also utilizes the new MIC/KEK/KCK length changes, since OWE dictates
the lengths of those keys.
Rather than hard coding to SHA256, we can pass in l_checksum_type
and use that SHA. This will allow for OWE/SAE/PWD to support more
curves that use different SHA algorithms for hashing.
OWE defines KEK/KCK lengths depending on group. This change adds a
case into handshake_get_key_sizes. With OWE we can determine the
key lengths based on the PMK length in the handshake.
In preparation for OWE supporting multiple groups eapol needed some
additional cases to handle the OWE AKM since OWE dictates the KEK,
KCK and MIC key lengths (depending on group).
Right now the PMK is hard coded to 32 bytes, which works for the vast
majority of cases. The only outlier is OWE which can generate a PMK
of 32, 48 or 64 bytes depending on the ECC group used. The PMK length
is already stored in the handshake, so now we can just pass that to
crypto_derive_pairwise_ptk
The crypto_ptk was hard coded for 16 byte KCK/KEK. Depending on the
AKM these can be up to 32 bytes. This changes completely removes the
crypto_ptk struct and adds getters to the handshake object for the
kck and kek. Like before the PTK is derived into a continuous buffer,
and the kck/kek getters take care of returning the proper key offset
depending on AKM.
To allow for larger than 16 byte keys aes_unwrap needed to be
modified to take the kek 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.
Non-802.11 AKMs can define their own key lengths. Currently only OWE does
this, and the MIC/KEK/KCK lengths will be determined by the PMK length so
we need to save it.
Make sure we don't pass NULLs to memcmp or l_memdup when the prefix
buffer is NULL. There's no point having callers pass dummy buffers if
they need to watch frames independent of the frame data.
Start using l_key_generate_dh_private and l_key_validate_dh_payload to
check for the disallowed corner case values in the DH private/public
values generated/received.
Some of the EAP methods don't require a clear-text identity to
be sent with the Identity Response packet. The mandatory identity
filed has resulted in unnecessary transmission of the garbage
values. This patch makes the Identity field to be optional and
shift responsibility to ensure its existence to the individual
methods if the field is required. All necessary identity checks
have been previously propagated to individual methods.
If a network is being forgotten, then make sure to reset connected_time.
Otherwise the rank logic thinks that the network is known which can
result in network_find_rank_index returning -1.
Found by sanitizer:
src/network.c:1329:23: runtime error: index -1 out of bounds for type
'double [64]'
==25412==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000421ab0 at pc 0x000000402faf bp 0x7fffffffdb00 sp 0x7fffffffdaf0
READ of size 4 at 0x000000421ab0 thread T0
#0 0x402fae in validate_mgmt_ies src/mpdu.c:128
#1 0x403ce8 in validate_probe_request_mmpdu src/mpdu.c:370
#2 0x404ef2 in validate_mgmt_mpdu src/mpdu.c:662
#3 0x405166 in mpdu_validate src/mpdu.c:706
#4 0x402529 in ie_order_test unit/test-mpdu.c:156
#5 0x418f49 in l_test_run ell/test.c:83
#6 0x402715 in main unit/test-mpdu.c:171
#7 0x7ffff5d43ed9 in __libc_start_main (/lib64/libc.so.6+0x20ed9)
#8 0x4019a9 in _start (/home/denkenz/iwd-master/unit/test-mpdu+0x4019a9)
This fixes the valgrind warning:
==14804== Conditional jump or move depends on uninitialised value(s)
==14804== at 0x402E56: sae_is_quadradic_residue (sae.c:218)
==14804== by 0x402E56: sae_compute_pwe (sae.c:272)
==14804== by 0x402E56: sae_build_commit (sae.c:333)
==14804== by 0x402E56: sae_send_commit (sae.c:591)
==14804== by 0x401CC3: test_confirm_after_accept (test-sae.c:454)
==14804== by 0x408A28: l_test_run (test.c:83)
==14804== by 0x401427: main (test-sae.c:566)
The return from l_ecc_point_from_data was not being checked for NULL,
which would cause a segfault if the peer sent an invalid point.
This adds a check and fails the protocol if p_element is NULL, as the
spec defines.
src/eap-ttls.c:766:50: error: ‘Password’ directive output may be truncated writing 8 bytes into a region of size between 1 and 72 [-Werror=format-truncation=]
snprintf(password_key, sizeof(password_key), "%sPassword", prefix);
^~~~~~~~
In file included from /usr/include/stdio.h:862,
from src/eap-ttls.c:28:
/usr/include/bits/stdio2.h:64:10: note: ‘__builtin___snprintf_chk’ output between 9 and 80 bytes into a destination of size 72
return __builtin___snprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__bos (__s), __fmt, __va_arg_pack ());
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Stop using l_pem_load_certificate which has been removed from ell, use
the same functions to load certificate files to validate them as those
used by the TLS implementation itself.
Check that the TLS logic has verified the server is trusted by the CA if
one was configured. This is more of an assert as ell intentionally only
allows empty certificate chains from the peer in server mode (if a CA
certficate is set) although this could be made configurable.
This should not change the behaviour except for fixing a rare crash
due to scan_cancel not working correctly when cancelling the first scan
request in the queue while a periodic scan was running, and potentially
other corner cases. To be able to better distinguish between a periodic
scan in progress and a scan request in progress add a sc->current_sr
field that points either at a scan request or is NULL when a periodic
scan is in ongoing. Move the triggered flag from scan_request and
scan_preiodic directly to scan_context so it's there together with
start_cmd_id. Hopefully make scan_cancel simpler/clearer.
Note sc->state and sc->triggered have similar semantics so one of them
may be easily removed. Also the wiphy_id parameter to the scan callback
is rather useless, note I temporarily pass 0 as the value on error but
perhaps it should be dropped.
In the name of failing earlier try to generate the PSK from the
passphrase as soon as we receive the passphrase or read it from the
file, mainly to validate it has the right number of characters.
The passphrase length currently gets validates inside
crypto_psk_from_passphrase which will be called when we receive a new
passphrase from the agent or when the config file has no PSK in it. We
do not do this when there's already both the PSK and the passphrase
available in the settings -- we can add that separately if needed.
The main difference with this is that scan_context removal will also
trigger the .destroy calls. Normally there won't be any requests left
during scan_context but if there were any we should call destroy on
them.
If we haven't sent a PMKID, and we're not running EAP, then ignore
whatever PMKID the AP sends us. Frequently the APs send us garbage in
this field. For PSK and related AKMs, if the PMK is wrong, then we
simply fail to generate a proper MIC and the handshake would fail at a
later stage anyway.
Fix incorrect usage of the caller’s scan triggered callback.
In case of a failure, destroy scan request and notify caller
about the issue by returning zero scan id instead of calling
callers’ scan triggered callback with an error code.
Using backtrace() is of no use when building with PIE (which most
distro compilers do by default) and prevents catching the coredump
for later retracing, which is needed since distros usually don't
install debug symbols by default either.
This patch thus only enables backtrace() when --enable-maintainer-mode
is passed and also tries to explicitly disable PIE.
ECDH was expecting the private key in LE, but the public key in BE byte ordering.
For consistency the ECDH now expect all inputs in LE byte ordering. It is up to
the caller to order the bytes appropriately.
This required adding some ecc_native2be/be2native calls in OWE
The changes to station.c are minor. Specifically,
station_build_handshake_rsn was modified to always build up the RSN
information, not just for SECURITY_8021X and SECURITY_PSK. This is
because OWE needs this RSN information, even though it is still
SECURITY_NONE. Since "regular" open networks don't need this, a check
was added (security == NONE && akm != OWE) which skips the RSN
building.
netdev.c needed to be changed in nearly the same manor as it was for
SAE. When connecting, we check if the AKM is for OWE, and if so create
a new OWE SM and start it. OWE handles all the ECDH, and netdev handles
sending CMD_AUTHENTICATE and CMD_ASSOCIATE when triggered by OWE. The
incoming authenticate/associate events just get forwarded to OWE as they
do with SAE.
This module is similar to SAE in that it communicates over authenticate
and associate frames. Creating a new OWE SM requires registering two TX
functions that handle sending the data out over CMD_AUTHENTICATE/ASSOCIATE,
as well as a complete function.
Once ready, calling owe_start will kick off the OWE process, first by
sending out an authenticate frame. There is nothing special here, since
OWE is done over the associate request/response.
After the authenticate response comes in OWE will send out the associate
frame which includes the ECDH public key, and then receive the AP's
public key via the associate response. From here OWE will use ECDH to
compute the shared secret, and the PMK/PMKID. Both are set into the
handshake object.
Assuming the PMK/PMKID are successfully computed the OWE complete callback
will trigger, meaning the 4-way handshake can begin using the PMK/PMKID
that were set in the handshake object.
The RFC (5869) for this implementation defines two functions,
HKDF-Extract and HKDF-Expand. The existing 'hkdf_256' was implementing
the Extract function, so it was renamed appropriately. The name was
changed for consistency when the Expand function will be added in the
future.
In the current version SECURITY_PSK was handled inside the is_rsn block
while the SECURITY_8021X was off in its own block. This was weird and a
bit misleading. Simplify the code flow through the use of a goto and
decrease the nesting level.
Also optimize out unnecessary use of scan_bss_get_rsn_info
In network_autoconnect, when the network was SECURITY_8021X there was no
check (for SECURITY_PSK) before calling network_load_psk. Since the
provisioning file was for an 8021x network neither PreSharedKey or
Passphrase existed so this would always fail. This fixes the 8021x failure
in testConnectAutoconnect.
During the handshake setup, if security != SECURITY_PSK then 8021x settings
would get set in the handshake object. This didn't appear to break anything
(e.g. Open/WEP) but its better to explicitly check that we are setting up
an 8021x network.
Check for HAVE_EXECINFO_H for all __iwd_backtrace_init usages.
Fixes:
src/main.o: In function `main':
main.c:(.text.startup+0x798): undefined reference to `__iwd_backtrace_init'
collect2: error: ld returned 1 exit status
A sorted list of hidden network BSSs observed in the recent scan
is kept for the informational purposes of the clients. In addition,
it has deprecated the usage of seen_hidden_networks variable.
Refactor the network->psk and network->passphrase loading and saving
logic to not require the PreSharedKey entry in the psk config file and
to generate network->psk lazily on request. Still cache the computed
PSK in memory and in the .psk file to avoid recomputing it which uses
many syscalls. While there update the ask_psk variable to
ask_passphrase because we're specifically asking for the passphrase.
According to the specification, Supported rates IE is supposed
to have a maximum length of eight rate bytes. In the wild an
Access Point is found to add 12 bytes of data instead of placing
excess rate bytes in an Extended Rates IE.
BSS: len 480
BSSID 44:39:C4:XX:XX:XX
Probe Response: true
TSF: 0 (0x0000000000000000)
IEs: len 188
...
Supported rates:
1.0(B) 2.0(B) 5.5(B) 6.0(B) 9.0 11.0(B) 12.0(B) 18.0 Mbit/s
24.0(B) 36.0 48.0 54.0 Mbit/s
82 84 8b 8c 12 96 98 24 b0 48 60 6c .......$.H`l
DSSS parameter set: channel 3
03
...
Any following IEs decode nicely, thus it seems that we can relax
Supported Rates IE length handling to support this thermostat.
After moving AP EAPoL code into eapol.c there were a few functions that
no longer needed to be public API's. These were changed to static's and
the header definition was removed.
Set an upper limit on a fragmented EAP-TLS request size similar to how
we do it in EAP-TTLS. While there make the code more similar to the
EAP-TTLS flag processing to keep them closer in sync. Note that the
spec suggests a 64KB limit but it's not clear if that is for the TLS
record or EAP request although it takes into account the whole TLS
negotiation so it might be good for both.
Some of the TTLS server implementations set the L flag in the fragment
packets other than the first one. To stay interoperable with such devices,
iwd is relaxing the L bit check.
Switch EAP-MD5 to use the common password setting key nomenclature.
The key name has been changed from PREFIX-MD5-Secret to PREFIX-Password.
Note: The old key name is supported.
In addition, this patch adds an ability to request Identity and/or
Password from user.
Adhoc was not waiting for BOTH handshakes to complete before adding the
new peer to the ConnectedPeers property. Actually waiting for the gtk/igtk
(in a previous commit) helps with this, but adhoc also needed to keep track
of which handshakes had completed, and only add the peer once BOTH were done.
This required a small change in netdev, where we memcmp the addresses from
both handshakes and only set the PTK on one.
Currently, netdev triggers the HANDSHAKE_COMPLETE event after completing
the SET_STATION (after setting the pairwise key). Depending on the timing
this may happen before the GTK/IGTK are set which will result in group
traffic not working initially (the GTK/IGTK would still get set, but group
traffic would not work immediately after DBus said you were connected, this
mainly poses a problem with autotests).
In order to fix this, several flags were added in netdev_handshake_state:
ptk_installed, gtk_installed, igtk_installed, and completed. Each of these
flags are set true when their respective keys are set, and in each key
callback we try to trigger the handshake complete event (assuming all the
flags are true). Initially the gtk/igtk flags are set to true, for reasons
explained below.
In the WPA2 case, all the key setter functions are called sequentially from
eapol. With this change, the PTK is now set AFTER the gtk/igtk. This is
because the gtk/igtk are optional and only set if group traffic is allowed.
If the gtk/igtk are not used, we set the PTK and can immediately trigger the
handshake complete event (since gtk_installed/igtk_installed are initialized
as true). When the gtk/igtk are being set, we immediately set their flags to
false and wait for their callbacks in addition to the PTK callback. Doing it
this way handles both group traffic and non group traffic paths.
WPA1 throws a wrench into this since the group keys are obtained in a
separate handshake. For this case a new flag was added to the handshake_state,
'wait_for_gtk'. This allows netdev to set the PTK after the initial 4-way,
but still wait for the gtk/igtk setters to get called before triggering the
handshake complete event. As a precaution, netdev sets a timeout that will
trigger if the gtk/igtk setters are never called. In this case we can still
complete the connection, but print a warning that group traffic will not be
allowed.
==1628== Invalid read of size 1
==1628== at 0x405E71: hardware_rekey_cb (netdev.c:1381)
==1628== by 0x444E5B: process_unicast (genl.c:415)
==1628== by 0x444E5B: received_data (genl.c:534)
==1628== by 0x442032: io_callback (io.c:126)
==1628== by 0x4414CD: l_main_iterate (main.c:387)
==1628== by 0x44158B: l_main_run (main.c:434)
==1628== by 0x403775: main (main.c:489)
==1628== Address 0x5475208 is 312 bytes inside a block of size 320 free'd
==1628== at 0x4C2ED18: free (vg_replace_malloc.c:530)
==1628== by 0x43D94D: l_queue_clear (queue.c:107)
==1628== by 0x43D998: l_queue_destroy (queue.c:82)
==1628== by 0x40B431: netdev_shutdown (netdev.c:4765)
==1628== by 0x403B17: iwd_shutdown (main.c:81)
==1628== by 0x4419D2: signal_callback (signal.c:82)
==1628== by 0x4414CD: l_main_iterate (main.c:387)
==1628== by 0x44158B: l_main_run (main.c:434)
==1628== by 0x403775: main (main.c:489)
==1628== Block was alloc'd at
==1628== at 0x4C2DB6B: malloc (vg_replace_malloc.c:299)
==1628== by 0x43CA4D: l_malloc (util.c:62)
==1628== by 0x40A853: netdev_create_from_genl (netdev.c:4517)
==1628== by 0x444E5B: process_unicast (genl.c:415)
==1628== by 0x444E5B: received_data (genl.c:534)
==1628== by 0x442032: io_callback (io.c:126)
==1628== by 0x4414CD: l_main_iterate (main.c:387)
==1628== by 0x44158B: l_main_run (main.c:434)
==1628== by 0x403775: main (main.c:489)
Adhoc requires 2 GTK's to be set, a single TX GTK and a per-mac RX GTK.
The per-mac RX GTK already gets set via netdev_set_gtk. The single TX GTK
is created the same as AP, where, upon the first station connecting a GTK
is generated and set in the kernel. Then any subsequent stations use
GET_KEY to retrieve the GTK and set it in the handshake.
AdHoc will also need the same functionality to verify and parse the
key sequence from GET_KEY. This block of code was moved from AP's
GET_KEY callback into nl80211_parse_get_key_seq.
Netdev/AP share several NL80211 commands and each has their own
builder API's. These were moved into a common file nl80211_util.[ch].
A helper was added to AP for building NEW_STATION to make the associate
callback look cleaner (rather than manually building NEW_STATION).
Check that netdev->device is not NULL before doing device_remove()
(which would crash) and emitting NETDEV_WATCH_EVENT_DEL. It may be
NULL if the initial RTM_SETLINK has failed to bring device UP.
If there are Ad-hoc BSSes they should be present in the scan results
together with regular APs as far as scan.c is concerned. But in
station mode we can't connect to them -- the Connect method will fail and
autoconnect would fail. Since we have no property to indicate a
network is an IBSS just filter these results out for now. There are
perhaps better solutions but the benefit is very low.
This is a replacement for station's static select_akm_suite. This was
done because wiphy can make a much more intellegent decision about the
akm suite by checking the wiphy supported features e.g. SAE support.
This allows a connection to hybrid WPA2/WPA3 AP's if SAE is not
supported in the kernel.