3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2025-08-01 16:37:26 +02:00

Compare commits

...

23 Commits
3.7 ... master

Author SHA1 Message Date
Marcel Holtmann
601d9b0e02 Release 3.9 2025-06-14 12:10:16 +02:00
James Prestwood
f209e00dde doc: add note about timeouts to Network.Connect()
Since netconfig is now part of the Connect() call from a DBus
perspective add a note indicating that this method has the potential
to take a very long time if there are issues with DHCP.
2025-06-05 10:02:28 -05:00
James Prestwood
86523b0597 auto-t: update several tests to work with netconfig refactor
Since the method return to Connect() and ConnectBssid() come after
netconfig some tests needed to be updated since they were waiting
for the method return before continuing. For timeout-based tests
specifically this caused them to fail since before they expected
the return to come before the connection was actually completed.
2025-06-05 10:02:23 -05:00
James Prestwood
85a2637fc5 auto-t: allow configurable DBus timeout/callbacks on connect{_bssid}
Let the caller specify the method timeout if there is an expectation
that it could take a long time.

For the conventional connect call (not the "bssid" debug variant) let
them pass their own callback handlers. This is useful if we don't
want to wait for the connect call to finish, but later get some
indication that it did finish either successfully or not.
2025-06-05 10:02:13 -05:00
James Prestwood
2f991918b1 station: include netconfig as part of the BSS retry logic
A netconfig failure results in a failed connection which restarts
autoconnect and prevents IWD from retrying the connection on any
other BSS's within the network as a whole. When autoconnect restarts
IWD will scan and choose the "best" BSS which is likely the same as
the prior attempt. If that BSS is somehow misconfigured as far as
DHCP goes, it will likely fail indefinitely and in turn cause IWD to
retry indefinitely.

To improve this netconfig has been adopted into the IWD's BSS retry
logic. If netconfig fails this will not result in IWD transitioning
to a disconnected state, and instead the BSS will be network
blacklisted and the next will be tried. Only once all BSS's have been
tried will IWD go into a disconnected state and start autoconnect
over.
2025-06-05 10:02:02 -05:00
James Prestwood
5b5a9b60fb station: fix DBus reply for Connect() with netconfig
When netconfig is enabled the DBus reply was being sent in
station_connect_ok(), before netconfig had even started. This would
result in a call to Connect() succeeding from a DBus perspective but
really netconfig still needed to complete before IWD transitioned
to a connected state.

Fixes: 72e7d3ceb83d ("station: Handle NETCONFIG_EVENT_FAILED")
2025-06-05 10:01:45 -05:00
James Prestwood
5287809043 network: make clearing network blacklist a separate operation
This adds a new API network_clear_blacklist() and removes this
functionality from network_connected(). This is done to support BSS
iteration when netconfig is enabled. Since a call to
network_connected() will happen prior to netconfig completing we
cannot clear the blacklist until netconfig has either passed or
failed.
2025-06-05 10:01:42 -05:00
James Prestwood
ea9ff2dcaf sae: prevent groups 21, 25, and 26 from being used
These groups are not working reliably and until that is fixed they
should be disabled.
2025-06-05 09:59:34 -05:00
James Prestwood
9dce36fe3d sae: check return on sae_send_commit()
If this fails, in some cases, -EAGAIN would be returned up to netdev
which would then assume a retry would be done automatically. This
would not in fact happen since it was an internal SAE failure which
would result in the connect method return to never get sent.

Now if sae_send_commit() fails, return -EPROTO which will cause
netdev to fail the connection.
2025-06-05 09:59:16 -05:00
Marcel Holtmann
c4718a5355 unit: Update precheck for WSC PBC test cases 2025-05-28 19:29:47 +02:00
James Prestwood
c9c8790ff2 netdev: support handling NL80211_CMD_ASSOC_COMEBACK
A BSS can temporarily reject associations and provide a delay that
the station should wait for before retrying. This is useful when
sane values are used, but taking it to the extreme an AP could
potentially request the client wait UINT32_MAX TU's which equates
to 49 days.

Either due to a bug, or worse by design, the kernel will wait for
however long that timeout is. Luckily the kernel also sends an event
to userspace with the amount of time it will be waiting. To guard
against excessive timeouts IWD will now handle this event and enforce
a maximum allowed value. If the timeout exceeds this IWD will
deauthenticate.
2025-05-28 12:06:43 -05:00
James Prestwood
d135bfc4b8 nl80211util: support parsing NL80211_ATTR_TIMEOUT 2025-05-28 12:06:36 -05:00
James Prestwood
e269beadba nl80211cmd: add NL80211_CMD_ASSOC_COMEBACK 2025-05-28 12:06:28 -05:00
James Prestwood
3e55fc855a auto-t: use renamed InitialAccessPointBusyTimeout 2025-05-19 16:38:54 -05:00
James Prestwood
c8d9936f9d station: utilize the AP_BUSY blacklist for denied auth/assoc
Specifically for the NO_MORE_STAS reason code, add the BSS to the
(now renamed) AP_BUSY blacklist to avoid roaming to this BSS for
the near future.

Since we are now handling individual reason codes differently the
whole IS_TEMPORARY_STATUS macro was removed and replaced with a
case statement.
2025-05-19 16:38:28 -05:00
James Prestwood
79940956ef docs: replace/deprecate InitialRoamRequestedTimeout
This is being replaced by InitialAccessPointBusyTimeout but will
still be supported until full removal.
2025-05-19 16:38:13 -05:00
James Prestwood
9f98c6c3c8 blacklist: rename ROAM_REQUESTED to AP_BUSY
The initial pass of this feature only envisioned BSS transition
management frames as the trigger to "roam blacklist" a BSS, hence
the original name. But some APs actually utilize status codes that
also indicate to the stations that they are busy, or not able to
handle more connections. This directly aligns with the original
motivation of the "roam blacklist" series and these events should
also trigger this type of blacklist.

First, since we will be applying this blacklist to cases other
than being told to roam, rename this reason code internally to
BLACKLIST_REASON_AP_BUSY. The config option is also being renamed
to [Blacklist].InitialAccessPointBusyTimeout while also supporting
the old config option, but warning that it is deprecated.
2025-05-19 16:37:13 -05:00
James Prestwood
93eef7b02d ap: implement pre-scanning to "unlock" frequencies
Some drivers/hardware are more strict about limiting use of
certain frequencies on startup until the regulatory domain has
been set. For most cards the only way to set the regulatory domain
is to scan and see BSS's nearby that advertise the country they
reside in.

This is particularly important for AP mode since AP's are always
emitting radiation from beacons and will not start until the desired
frequency is both enabled and allows IR. To make this process
seamless in IWD we will first check that the desired frequency is
enabled/IR and if not issue a scan to (hopefully) get the regulatory
domain set.
2025-05-19 16:36:45 -05:00
Marcel Holtmann
26ed1f8b9f Release 3.8 2025-05-07 13:41:49 +02:00
Marcel Holtmann
243db1d256 build: Require at least version 0.77 when building with external ELL 2025-05-07 12:47:42 +02:00
Marcel Holtmann
5224b0b0e7 unit: Use test precheck feature to check for kernel capabilities 2025-05-07 09:54:22 +02:00
Marcel Holtmann
3267d356d2 unit: The precheck function also takes test data as parameter 2025-05-05 20:41:56 +02:00
Marcel Holtmann
78f4e6240e unit: Use new precheck feature for storage encryption test 2025-05-05 19:37:34 +02:00
32 changed files with 634 additions and 395 deletions

View File

@ -1,3 +1,12 @@
ver 3.9:
Fix issue with Access Point mode and frequency unlocking.
Fix issue with network configuration and BSS retry logic.
Fix issue with handling busy notification from Access Point.
Fix issue with handling P-192, P-224 and P-521 for SAE.
ver 3.8:
Fix issue with handling unit tests and missing kernel features.
ver 3.7:
Fix issue with handling length of EncryptedSecurity.
Fix issue with handling empty affinities lists.

View File

@ -3,4 +3,4 @@ RoamThreshold=-72
CriticalRoamThreshold=-72
[Blacklist]
InitialRoamRequestedTimeout=20
InitialAccessPointBusyTimeout=20

View File

@ -91,16 +91,11 @@ class Test(unittest.TestCase):
# using the same static config. The new client's ACD client should
# detect an IP conflict and not allow the device to reach the
# "connected" state although the DBus .Connect call will succeed.
ordered_network.network_object.connect()
self.assertEqual(dev2.state, iwd.DeviceState.connecting)
try:
# We should either stay in "connecting" indefinitely or move to
# "disconnecting"
condition = 'obj.state != DeviceState.connecting'
iwd_ns0_1.wait_for_object_condition(dev2, condition, max_wait=21)
self.assertEqual(dev2.state, iwd.DeviceState.disconnecting)
except TimeoutError:
dev2.disconnect()
with self.assertRaises(iwd.FailedEx):
ordered_network.network_object.connect(timeout=500)
condition = 'obj.state == DeviceState.disconnected'
iwd_ns0_1.wait_for_object_condition(dev2, condition, max_wait=21)
iwd_ns0_1.unregister_psk_agent(psk_agent_ns0_1)
del dev2

View File

@ -8,6 +8,8 @@ from iwd import PSKAgent
from iwd import NetworkType
class Test(unittest.TestCase):
def connect_failure(self, ex):
self.failure_triggered = True
def test_netconfig_timeout(self):
IWD.copy_to_storage('autoconnect.psk', name='ap-ns1.psk')
@ -27,23 +29,34 @@ class Test(unittest.TestCase):
condition = 'not obj.connected'
wd.wait_for_object_condition(ordered_network.network_object, condition)
ordered_network.network_object.connect()
self.failure_triggered = False
condition = 'obj.state == DeviceState.connecting'
# Set our error handler here so we can check if it fails
ordered_network.network_object.connect(
wait=False,
timeout=1000,
error_handler=self.connect_failure
)
# IWD should attempt to try both BSS's with both failing netconfig.
# Then the autoconnect list should be exhausted, and IWD should
# transition to a disconnected state, then proceed to full autoconnect.
device.wait_for_event("netconfig-failed", timeout=1000)
device.wait_for_event("netconfig-failed", timeout=1000)
device.wait_for_event("disconnected")
device.wait_for_event("autoconnect_full")
# The connect call should have failed
self.assertTrue(self.failure_triggered)
condition = "obj.scanning"
wd.wait_for_object_condition(device, condition)
condition = "not obj.scanning"
wd.wait_for_object_condition(device, condition)
device.wait_for_event("connecting (netconfig)")
# Netconfig should fail, and IWD should disconnect
from_condition = 'obj.state == DeviceState.connecting'
to_condition = 'obj.state == DeviceState.disconnecting'
wd.wait_for_object_change(device, from_condition, to_condition, max_wait=60)
# Autoconnect should then try again
condition = 'obj.state == DeviceState.connecting'
wd.wait_for_object_condition(device, condition)
device.wait_for_event("connecting (netconfig)")
# IWD should attempt to connect, but it will of course fail again.
device.wait_for_event("netconfig-failed", timeout=1000)
device.disconnect()
condition = 'obj.state == DeviceState.disconnected'

View File

@ -19,7 +19,7 @@ class Test(unittest.TestCase):
device = wd.list_devices(1)[0]
device.get_ordered_network('TestFT', full_scan=True)
device.connect_bssid(self.bss_hostapd[1].bssid)
device.connect_bssid(self.bss_hostapd[1].bssid, wait=False)
self.bss_hostapd[1].wait_for_event(f'AP-STA-CONNECTED {device.address}')
device.wait_for_event("connecting (netconfig)")

View File

@ -112,8 +112,8 @@ class AsyncOpAbstract(object):
self._is_completed = True
self._exception = _convert_dbus_ex(ex)
def _wait_for_async_op(self):
ctx.non_block_wait(lambda s: s._is_completed, 30, self, exception=None)
def _wait_for_async_op(self, timeout=50):
ctx.non_block_wait(lambda s: s._is_completed, timeout, self, exception=None)
self._is_completed = False
if self._exception is not None:
@ -280,8 +280,15 @@ class StationDebug(IWDDBusAbstract):
def autoconnect(self):
return self._properties['AutoConnect']
def connect_bssid(self, address):
self._iface.ConnectBssid(dbus.ByteArray.fromhex(address.replace(':', '')))
def connect_bssid(self, address, wait=True):
self._iface.ConnectBssid(
dbus.ByteArray.fromhex(address.replace(':', '')),
reply_handler=self._success,
error_handler=self._failure
)
if wait:
self._wait_for_async_op()
def roam(self, address):
self._iface.Roam(dbus.ByteArray.fromhex(address.replace(':', '')))
@ -870,8 +877,8 @@ class Device(IWDDBusAbstract):
def stop_adhoc(self):
self._prop_proxy.Set(IWD_DEVICE_INTERFACE, 'Mode', 'station')
def connect_bssid(self, address):
self._station_debug.connect_bssid(address)
def connect_bssid(self, address, wait=True):
self._station_debug.connect_bssid(address, wait=wait)
def roam(self, address):
self._station_debug.roam(address)
@ -999,7 +1006,7 @@ class Network(IWDDBusAbstract):
def extended_service_set(self):
return self._properties['ExtendedServiceSet']
def connect(self, wait=True):
def connect(self, wait=True, timeout=50, reply_handler=None, error_handler=None):
'''
Connect to the network. Request the device implied by the object
path to connect to specified network.
@ -1014,12 +1021,19 @@ class Network(IWDDBusAbstract):
@rtype: void
'''
if not reply_handler:
reply_handler = self._success
if not error_handler:
error_handler = self._failure
self._iface.Connect(dbus_interface=self._iface_name,
reply_handler=self._success,
error_handler=self._failure)
reply_handler=reply_handler,
error_handler=error_handler,
timeout=timeout)
if wait:
self._wait_for_async_op()
self._wait_for_async_op(timeout=timeout)
def __str__(self, prefix = ''):
return prefix + 'Network:\n' \

View File

@ -1,5 +1,5 @@
AC_PREREQ([2.69])
AC_INIT([iwd],[3.7])
AC_INIT([iwd],[3.9])
AC_CONFIG_HEADERS(config.h)
AC_CONFIG_AUX_DIR(build-aux)
@ -300,7 +300,7 @@ if (test "${enable_external_ell}" = "yes"); then
test "${enable_monitor}" != "no" ||
test "${enable_wired}" = "yes" ||
test "${enable_hwsim}" = "yes"); then
ell_min_version="0.72"
ell_min_version="0.77"
else
ell_min_version="0.5"
fi

View File

@ -11,6 +11,12 @@ Methods void Connect()
the object path to connect to specified network.
Connecting to WEP networks is not supported.
Note: When [General].EnableNetworkConfiguration is set
to true a call to Connect() has the potential to take
a significant amount of time. Specifically if DHCP is
either slow, or is unable to complete. The timeout for
DHCP is roughly 30 seconds per BSS.
Possible errors: net.connman.iwd.Aborted
net.connman.iwd.Busy
net.connman.iwd.Failed

View File

@ -109,6 +109,8 @@ struct ap_state {
struct l_timeout *rekey_timeout;
unsigned int rekey_time;
uint32_t pre_scan_cmd_id;
bool started : 1;
bool gtk_set : 1;
bool netconfig_set_addr4 : 1;
@ -354,6 +356,12 @@ static void ap_reset(struct ap_state *ap)
l_timeout_remove(ap->rekey_timeout);
ap->rekey_timeout = NULL;
}
if (ap->pre_scan_cmd_id) {
scan_cancel(netdev_get_wdev_id(ap->netdev),
ap->pre_scan_cmd_id);
ap->pre_scan_cmd_id = 0;
}
}
static bool ap_event_done(struct ap_state *ap, bool prev_in_event)
@ -3852,6 +3860,70 @@ static int ap_load_config(struct ap_state *ap, const struct l_settings *config,
return 0;
}
static void ap_pre_scan_trigger(int err, void *user_data)
{
struct ap_state *ap = user_data;
if (err < 0) {
l_error("AP pre-scan failed: %i", err);
ap_start_failed(ap, err);
return;
}
}
static bool ap_check_channel(struct ap_state *ap)
{
const struct band_freq_attrs *freq_attr;
freq_attr = wiphy_get_frequency_info(netdev_get_wiphy(ap->netdev),
band_channel_to_freq(ap->channel, ap->band));
if (L_WARN_ON(!freq_attr))
return false;
/* Check if disabled/no-IR */
if (freq_attr->disabled || freq_attr->no_ir)
return false;
return true;
}
static bool ap_pre_scan_notify(int err, struct l_queue *bss_list,
const struct scan_freq_set *freqs,
void *user_data)
{
struct ap_state *ap = user_data;
if (!ap_check_channel(ap)) {
l_error("Unable to channel %u even after pre-scan",
ap->channel);
goto error;
}
if (ap_start_send(ap))
return false;
error:
ap_start_failed(ap, -ENOTSUP);
return false;
}
static void ap_pre_scan_destroy(void *user_data)
{
struct ap_state *ap = user_data;
ap->pre_scan_cmd_id = 0;
}
static bool ap_pre_scan(struct ap_state *ap)
{
ap->pre_scan_cmd_id = scan_passive(netdev_get_wdev_id(ap->netdev),
NULL, ap_pre_scan_trigger,
ap_pre_scan_notify,
ap, ap_pre_scan_destroy);
return ap->pre_scan_cmd_id != 0;
}
/*
* Start a simple independent WPA2 AP on given netdev.
*
@ -3962,6 +4034,20 @@ struct ap_state *ap_start(struct netdev *netdev, struct l_settings *config,
return ap;
}
if (!ap_check_channel(ap)) {
l_debug("Channel %u is disabled/no-IR, pre-scanning",
ap->channel);
if (ap_pre_scan(ap)) {
if (err_out)
*err_out = 0;
return ap;
}
goto error;
}
if (ap_start_send(ap)) {
if (err_out)
*err_out = 0;

View File

@ -45,7 +45,7 @@
static uint64_t blacklist_multiplier;
static uint64_t blacklist_initial_timeout;
static uint64_t blacklist_roam_initial_timeout;
static uint64_t blacklist_ap_busy_initial_timeout;
static uint64_t blacklist_max_timeout;
struct blacklist_entry {
@ -67,8 +67,8 @@ static uint64_t get_reason_timeout(enum blacklist_reason reason)
switch (reason) {
case BLACKLIST_REASON_CONNECT_FAILED:
return blacklist_initial_timeout;
case BLACKLIST_REASON_ROAM_REQUESTED:
return blacklist_roam_initial_timeout;
case BLACKLIST_REASON_AP_BUSY:
return blacklist_ap_busy_initial_timeout;
default:
l_warn("Unhandled blacklist reason: %u", reason);
return 0;
@ -218,11 +218,19 @@ static int blacklist_init(void)
if (!l_settings_get_uint64(config, "Blacklist",
"InitialRoamRequestedTimeout",
&blacklist_roam_initial_timeout))
blacklist_roam_initial_timeout = BLACKLIST_DEFAULT_TIMEOUT;
&blacklist_ap_busy_initial_timeout))
blacklist_ap_busy_initial_timeout = BLACKLIST_DEFAULT_TIMEOUT;
else
l_warn("[Blacklist].InitialRoamRequestedTimeout is deprecated, "
"use [Blacklist].InitialAccessPointBusyTimeout");
if (!l_settings_get_uint64(config, "Blacklist",
"InitialAccessPointBusyTimeout",
&blacklist_ap_busy_initial_timeout))
blacklist_ap_busy_initial_timeout = BLACKLIST_DEFAULT_TIMEOUT;
/* For easier user configuration the timeout values are in seconds */
blacklist_roam_initial_timeout *= L_USEC_PER_SEC;
blacklist_ap_busy_initial_timeout *= L_USEC_PER_SEC;
if (!l_settings_get_uint64(config, "Blacklist",
"Multiplier",

View File

@ -27,12 +27,14 @@ enum blacklist_reason {
*/
BLACKLIST_REASON_CONNECT_FAILED,
/*
* This type of blacklist is added when a BSS requests IWD roams
* elsewhere. This is to aid in preventing IWD from roaming/connecting
* back to that BSS in the future unless there are no other "good"
* candidates to connect to.
* This type of blacklist is added when an AP indicates that its unable
* to handle more connections. This is done via BSS-TM requests or
* denied authentications/associations with certain status codes.
*
* Once this type of blacklist is applied to a BSS IWD will attempt to
* avoid roaming to it for a configured period of time.
*/
BLACKLIST_REASON_ROAM_REQUESTED,
BLACKLIST_REASON_AP_BUSY,
};
void blacklist_add_bss(const uint8_t *addr, enum blacklist_reason reason);

View File

@ -292,12 +292,22 @@ control how long a misbehaved BSS spends on the blacklist.
The initial time that a BSS spends on the blacklist. Setting this to zero
will disable blacklisting functionality in IWD.
* - InitialRoamRequestedTimeout
* - InitialRoamRequestedTimeout (**deprecated**)
- Values: uint64 value in seconds (default: **30**)
The initial time that a BSS will be marked after a BSS requests a roam.
This is to aid in avoiding roaming back to BSS's which are likely
overloaded. Setting this to zero will disabled this form of blacklisting.
This setting is deprecated, please use
[Blacklist].InitialAccessPointBusyTimeout instead.
* - InitialAccessPointBusyTimeout
- Values: uint64 value in seconds (default: **30**)
The initial time that a BSS will be blacklisted after indicating it
cannot handle more connections. This is triggered by either a BSS
transition management request (telling IWD to roam elsewhere) or by a
denied authentication or association with the NO_MORE_STAS status code.
Once a BSS is blacklisted in this manor IWD will attempt to avoid it for
the configured amount of time.
* - Multiplier
- Values: unsigned int value greater than zero, in seconds
(default: **30**)

View File

@ -5451,6 +5451,39 @@ static void netdev_michael_mic_failure(struct l_genl_msg *msg,
l_debug("ifindex=%u key_idx=%u type=%u", netdev->index, idx, type);
}
#define MAX_COMEBACK_DELAY 1200
static void netdev_assoc_comeback(struct l_genl_msg *msg,
struct netdev *netdev)
{
const uint8_t *mac;
uint32_t timeout;
if (L_WARN_ON(!netdev->connected))
return;
if (nl80211_parse_attrs(msg, NL80211_ATTR_MAC, &mac,
NL80211_ATTR_TIMEOUT, &timeout,
NL80211_ATTR_UNSPEC) < 0)
return;
if (L_WARN_ON(memcmp(mac, netdev->handshake->aa, ETH_ALEN)))
return;
if (timeout <= MAX_COMEBACK_DELAY) {
l_debug(MAC" requested an association comeback delay of %u TU",
MAC_STR(netdev->handshake->aa), timeout);
return;
}
l_debug("Comeback delay of %u exceeded maximum of %u, deauthenticating",
timeout, MAX_COMEBACK_DELAY);
netdev_deauth_and_fail_connection(netdev,
NETDEV_RESULT_ASSOCIATION_FAILED,
MMPDU_STATUS_CODE_REFUSED_TEMPORARILY);
}
static void netdev_mlme_notify(struct l_genl_msg *msg, void *user_data)
{
struct netdev *netdev = NULL;
@ -5504,6 +5537,9 @@ static void netdev_mlme_notify(struct l_genl_msg *msg, void *user_data)
case NL80211_CMD_MICHAEL_MIC_FAILURE:
netdev_michael_mic_failure(msg, netdev);
break;
case NL80211_CMD_ASSOC_COMEBACK:
netdev_assoc_comeback(msg, netdev);
break;
}
}

View File

@ -168,6 +168,11 @@ static bool network_secret_check_cacheable(void *data, void *user_data)
return false;
}
void network_clear_blacklist(struct network *network)
{
l_queue_clear(network->blacklist, NULL);
}
void network_connected(struct network *network)
{
enum security security = network_get_security(network);
@ -198,8 +203,6 @@ void network_connected(struct network *network)
l_queue_foreach_remove(network->secrets,
network_secret_check_cacheable, network);
l_queue_clear(network->blacklist, NULL);
network->provisioning_hidden = false;
}
@ -207,7 +210,7 @@ void network_disconnected(struct network *network)
{
network_settings_close(network);
l_queue_clear(network->blacklist, NULL);
network_clear_blacklist(network);
if (network->provisioning_hidden)
station_hide_network(network->station, network);

View File

@ -74,6 +74,7 @@ bool network_bss_update(struct network *network, struct scan_bss *bss);
const char *network_bss_get_path(const struct network *network,
const struct scan_bss *bss);
bool network_bss_list_isempty(struct network *network);
void network_clear_blacklist(struct network *network);
const char *__network_path_append_bss(const char *network_path,
const struct scan_bss *bss);

View File

@ -177,6 +177,7 @@ static const struct {
{ NL80211_CMD_UNPROT_BEACON, "Unprotected Beacon" },
{ NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS,
"Control Port TX Status" },
{ NL80211_CMD_ASSOC_COMEBACK, "Association comeback delay" },
{ }
};

View File

@ -190,6 +190,7 @@ static attr_handler handler_for_nl80211(int type)
case NL80211_ATTR_CENTER_FREQ2:
case NL80211_ATTR_AKM_SUITES:
case NL80211_ATTR_EXTERNAL_AUTH_ACTION:
case NL80211_ATTR_TIMEOUT:
return extract_uint32;
case NL80211_ATTR_FRAME:
return extract_iovec;

View File

@ -169,6 +169,14 @@ static int sae_choose_next_group(struct sae_sm *sm)
!sm->handshake->ecc_sae_pts[sm->group_retry])
continue;
/*
* TODO: Groups for P192, P224 and P521 are currently
* non-functional with SAE. Until this is fixed we need to
* avoid these groups from being used.
*/
if (group == 21 || group == 25 || group == 26)
continue;
break;
}
@ -994,7 +1002,8 @@ static int sae_process_anti_clogging(struct sae_sm *sm, const uint8_t *ptr,
sm->token_len = len;
sm->sync = 0;
sae_send_commit(sm, true);
if (L_WARN_ON(!sae_send_commit(sm, true)))
return -EPROTO;
return -EAGAIN;
}
@ -1074,7 +1083,9 @@ static int sae_verify_committed(struct sae_sm *sm, uint16_t transaction,
return -ETIMEDOUT;
sm->sync++;
sae_send_commit(sm, true);
if (L_WARN_ON(!sae_send_commit(sm, true)))
return -EPROTO;
return -EAGAIN;
}
@ -1129,7 +1140,9 @@ static int sae_verify_committed(struct sae_sm *sm, uint16_t transaction,
sm->group);
sm->sync = 0;
sae_send_commit(sm, false);
if (L_WARN_ON(!sae_send_commit(sm, false)))
return -EPROTO;
return -EAGAIN;
}
@ -1294,7 +1307,8 @@ static int sae_verify_confirmed(struct sae_sm *sm, uint16_t trans,
sm->sync++;
sm->sc++;
sae_send_commit(sm, true);
if (L_WARN_ON(!sae_send_commit(sm, true)))
return -EPROTO;
if (!sae_send_confirm(sm))
return -EPROTO;

View File

@ -191,8 +191,7 @@ static uint32_t evaluate_bss_group_rank(const uint8_t *addr, uint32_t freq,
if (blacklist_contains_bss(addr, BLACKLIST_REASON_CONNECT_FAILED))
return 0;
roam_blacklist = blacklist_contains_bss(addr,
BLACKLIST_REASON_ROAM_REQUESTED);
roam_blacklist = blacklist_contains_bss(addr, BLACKLIST_REASON_AP_BUSY);
good_signal = signal >= netdev_get_low_signal_threshold(freq);
if (good_signal)
@ -1796,6 +1795,15 @@ static void station_enter_state(struct station *station,
periodic_scan_stop(station);
break;
case STATION_STATE_CONNECTED:
network_clear_blacklist(station->connected_network);
if (station->connect_pending) {
struct l_dbus_message *reply =
l_dbus_message_new_method_return(
station->connect_pending);
dbus_pending_reply(&station->connect_pending, reply);
}
l_dbus_object_add_interface(dbus,
netdev_get_path(station->netdev),
IWD_STATION_DIAGNOSTIC_INTERFACE,
@ -2215,6 +2223,26 @@ static void station_early_neighbor_report_cb(struct netdev *netdev, int err,
&station->roam_freqs);
}
static bool station_try_next_bss(struct station *station)
{
struct scan_bss *next;
int ret;
next = network_bss_select(station->connected_network, false);
if (!next)
return false;
ret = __station_connect_network(station, station->connected_network,
next, station->state);
if (ret < 0)
return false;
l_debug("Attempting to connect to next BSS "MAC, MAC_STR(next->addr));
return true;
}
static bool station_can_fast_transition(struct station *station,
struct handshake_state *hs,
struct scan_bss *bss)
@ -2257,28 +2285,26 @@ static bool station_can_fast_transition(struct station *station,
return true;
}
static void station_disconnect_on_error_cb(struct netdev *netdev, bool success,
void *user_data)
static void station_disconnect_on_netconfig_failed(struct netdev *netdev,
bool success,
void *user_data)
{
struct station *station = user_data;
bool continue_autoconnect;
station_enter_state(station, STATION_STATE_DISCONNECTED);
continue_autoconnect = station->state == STATION_STATE_CONNECTING_AUTO;
if (continue_autoconnect) {
if (station_autoconnect_next(station) < 0) {
l_debug("Nothing left on autoconnect list");
station_enter_state(station,
STATION_STATE_AUTOCONNECT_FULL);
}
if (station_try_next_bss(station))
return;
if (station->connect_pending) {
struct l_dbus_message *reply = dbus_error_failed(
station->connect_pending);
dbus_pending_reply(&station->connect_pending, reply);
}
if (station->autoconnect)
station_enter_state(station, STATION_STATE_AUTOCONNECT_QUICK);
station_reset_connection_state(station);
station_enter_state(station, STATION_STATE_DISCONNECTED);
station_enter_state(station, STATION_STATE_AUTOCONNECT_FULL);
}
static void station_netconfig_event_handler(enum netconfig_event event,
@ -2291,23 +2317,20 @@ static void station_netconfig_event_handler(enum netconfig_event event,
station_enter_state(station, STATION_STATE_CONNECTED);
break;
case NETCONFIG_EVENT_FAILED:
if (station->connect_pending) {
struct l_dbus_message *reply = dbus_error_failed(
station->connect_pending);
station_debug_event(station, "netconfig-failed");
dbus_pending_reply(&station->connect_pending, reply);
}
netconfig_reset(station->netconfig);
if (station->state == STATION_STATE_NETCONFIG)
network_connect_failed(station->connected_network,
false);
netdev_disconnect(station->netdev,
station_disconnect_on_error_cb,
station);
station_reset_connection_state(station);
network_blacklist_add(station->connected_network,
station->connected_bss);
station_enter_state(station, STATION_STATE_DISCONNECTING);
netdev_disconnect(station->netdev,
station_disconnect_on_netconfig_failed,
station);
break;
default:
l_error("station: Unsupported netconfig event: %d.", event);
@ -3326,7 +3349,7 @@ static void station_ap_directed_roam(struct station *station,
}
blacklist_add_bss(station->connected_bss->addr,
BLACKLIST_REASON_ROAM_REQUESTED);
BLACKLIST_REASON_AP_BUSY);
station_debug_event(station, "ap-roam-blacklist-added");
/*
@ -3410,26 +3433,6 @@ static void station_event_channel_switched(struct station *station,
network_bss_update(network, station->connected_bss);
}
static bool station_try_next_bss(struct station *station)
{
struct scan_bss *next;
int ret;
next = network_bss_select(station->connected_network, false);
if (!next)
return false;
ret = __station_connect_network(station, station->connected_network,
next, station->state);
if (ret < 0)
return false;
l_debug("Attempting to connect to next BSS "MAC, MAC_STR(next->addr));
return true;
}
static bool station_retry_owe_default_group(struct station *station)
{
/*
@ -3523,13 +3526,6 @@ static bool station_pmksa_fallback(struct station *station, uint16_t status)
return true;
}
/* A bit more concise for trying to fit these into 80 characters */
#define IS_TEMPORARY_STATUS(code) \
((code) == MMPDU_STATUS_CODE_DENIED_UNSUFFICIENT_BANDWIDTH || \
(code) == MMPDU_STATUS_CODE_DENIED_POOR_CHAN_CONDITIONS || \
(code) == MMPDU_STATUS_CODE_REJECTED_WITH_SUGG_BSS_TRANS || \
(code) == MMPDU_STATUS_CODE_DENIED_NO_MORE_STAS)
static bool station_retry_with_status(struct station *station,
uint16_t status_code)
{
@ -3537,19 +3533,37 @@ static bool station_retry_with_status(struct station *station,
if (station_pmksa_fallback(station, status_code))
goto try_next;
switch (status_code) {
/*
* Certain Auth/Assoc failures should not cause a timeout blacklist.
* In these cases we want to only temporarily blacklist the BSS until
* the connection is complete.
*
*/
case MMPDU_STATUS_CODE_DENIED_UNSUFFICIENT_BANDWIDTH:
case MMPDU_STATUS_CODE_DENIED_POOR_CHAN_CONDITIONS:
/*
* TODO: The WITH_SUGG_BSS_TRANS case should also include a neighbor
* report IE in the frame. This would allow us to target a
* specific BSS on our next attempt. There is currently no way to
* obtain that IE, but this should be done in the future.
*/
case MMPDU_STATUS_CODE_REJECTED_WITH_SUGG_BSS_TRANS:
break;
/*
* If a BSS is indicating its unable to handle more connections we will
* blacklist this the same way we do for BSS's issuing BSS-TM requests
* thereby avoiding roams to this BSS for the configured timeout.
*/
if (!IS_TEMPORARY_STATUS(status_code))
case MMPDU_STATUS_CODE_DENIED_NO_MORE_STAS:
blacklist_add_bss(station->connected_bss->addr,
BLACKLIST_REASON_AP_BUSY);
break;
/* For any other status codes, blacklist the BSS */
default:
blacklist_add_bss(station->connected_bss->addr,
BLACKLIST_REASON_CONNECT_FAILED);
break;
}
/*
* Unconditionally network blacklist the BSS if we are retrying. This
@ -3571,13 +3585,6 @@ static void station_connect_ok(struct station *station)
l_debug("");
if (station->connect_pending) {
struct l_dbus_message *reply =
l_dbus_message_new_method_return(
station->connect_pending);
dbus_pending_reply(&station->connect_pending, reply);
}
/*
* Get a neighbor report now so future roams can avoid waiting for
* a report at that time

View File

@ -138,20 +138,22 @@ static const struct cmac_data example_4 = {
.tag_len = sizeof(tag_4),
};
static bool test_precheck(const void *data)
{
return l_checksum_cmac_aes_supported();
}
#define add_test(name, func, data) l_test_add_data_func_precheck(name, data, \
func, test_precheck, 0)
int main(int argc, char *argv[])
{
l_test_init(&argc, &argv);
if (!l_checksum_cmac_aes_supported()) {
printf("AES-CMAC support missing, skipping...\n");
goto done;
}
add_test("/cmac-aes/Example 1", cmac_test, &example_1);
add_test("/cmac-aes/Example 2", cmac_test, &example_2);
add_test("/cmac-aes/Example 3", cmac_test, &example_3);
add_test("/cmac-aes/Example 4", cmac_test, &example_4);
l_test_add("/cmac-aes/Example 1", cmac_test, &example_1);
l_test_add("/cmac-aes/Example 2", cmac_test, &example_2);
l_test_add("/cmac-aes/Example 3", cmac_test, &example_3);
l_test_add("/cmac-aes/Example 4", cmac_test, &example_4);
done:
return l_test_run();
}

View File

@ -403,40 +403,32 @@ static void aes_siv_test(const void *data)
assert(memcmp(decrypted, plaintext, sizeof(decrypted)) == 0);
}
static bool test_precheck(const void *data)
{
return (l_cipher_is_supported(L_CIPHER_AES) &&
l_checksum_is_supported(L_CHECKSUM_SHA1, true));
}
#define add_test(name, func, data) l_test_add_data_func_precheck(name, data, \
func, test_precheck, 0)
int main(int argc, char *argv[])
{
l_test_init(&argc, &argv);
if (!l_checksum_is_supported(L_CHECKSUM_SHA1, true)) {
printf("SHA1 support missing, skipping...\n");
goto done;
}
add_test("/Passphrase Generator/PSK Test Case 1",
psk_test, &psk_test_case_1);
add_test("/Passphrase Generator/PSK Test Case 2",
psk_test, &psk_test_case_2);
add_test("/Passphrase Generator/PSK Test Case 3",
psk_test, &psk_test_case_3);
if (!l_cipher_is_supported(L_CIPHER_AES)) {
printf("AES support missing, skipping...\n");
goto done;
}
add_test("/PTK Derivation/PTK Test Case 1", ptk_test, &ptk_test_1);
add_test("/PTK Derivation/PTK Test Case 2", ptk_test, &ptk_test_2);
add_test("/PTK Derivation/PTK Test Case 3", ptk_test, &ptk_test_3);
add_test("/PTK Derivation/PTK Test Case 4", ptk_test, &ptk_test_4);
l_test_add("/Passphrase Generator/PSK Test Case 1",
psk_test, &psk_test_case_1);
l_test_add("/Passphrase Generator/PSK Test Case 2",
psk_test, &psk_test_case_2);
l_test_add("/Passphrase Generator/PSK Test Case 3",
psk_test, &psk_test_case_3);
add_test("/AES Key-wrap/Wrap & unwrap", aes_wrap_test, NULL);
add_test("/AES-SIV", aes_siv_test, NULL);
l_test_add("/PTK Derivation/PTK Test Case 1",
ptk_test, &ptk_test_1);
l_test_add("/PTK Derivation/PTK Test Case 2",
ptk_test, &ptk_test_2);
l_test_add("/PTK Derivation/PTK Test Case 3",
ptk_test, &ptk_test_3);
l_test_add("/PTK Derivation/PTK Test Case 4",
ptk_test, &ptk_test_4);
l_test_add("/AES Key-wrap/Wrap & unwrap",
aes_wrap_test, NULL);
l_test_add("/AES-SIV", aes_siv_test, NULL);
done:
return l_test_run();
}

View File

@ -577,22 +577,25 @@ static void test_pkex_key_derivation(const void *user_data)
CHECK_FROM_STR(vector->v, tmp, 32);
}
static bool test_precheck(const void *data)
{
return (l_getrandom_is_supported() &&
l_checksum_is_supported(L_CHECKSUM_SHA256, true));
}
#define add_test(name, func, data) l_test_add_data_func_precheck(name, data, \
func, test_precheck, 0)
int main(int argc, char *argv[])
{
l_test_init(&argc, &argv);
if (l_checksum_is_supported(L_CHECKSUM_SHA256, true) &&
l_getrandom_is_supported()) {
l_test_add("DPP test responder-only key derivation",
test_key_derivation,
&responder_only_p256);
l_test_add("DPP test mutual key derivation",
test_key_derivation,
&mutual_p256);
l_test_add("DPP test PKEX key derivation",
test_pkex_key_derivation,
&pkex_vector);
}
add_test("DPP test responder-only key derivation", test_key_derivation,
&responder_only_p256);
add_test("DPP test mutual key derivation", test_key_derivation,
&mutual_p256);
add_test("DPP test PKEX key derivation", test_pkex_key_derivation,
&pkex_vector);
l_test_add("DPP URI parse", test_uri_parse, &all_values);
l_test_add("DPP URI no type", test_uri_parse, &no_type);

View File

@ -131,27 +131,23 @@ static void test_get_asym_key(const void *data)
assert(!memcmp(msk, m_session_key, sizeof(m_session_key)));
}
static bool test_precheck(const void *data)
{
return l_checksum_is_supported(L_CHECKSUM_MD4, false);
}
#define add_test(name, func) l_test_add_func_precheck(name, func, \
test_precheck, 0)
int main(int argc, char *argv[])
{
l_test_init(&argc, &argv);
if (!l_checksum_is_supported(L_CHECKSUM_MD4, false)) {
printf("MD4 support missing, skipping...\n");
goto done;
}
add_test("MSHAPv2 nt_password-hash", test_nt_password_hash);
add_test("MSHAPv2 generate_nt_response", test_generate_nt_response);
add_test("MSHAPv2 get_master_key", test_get_master_key);
add_test("MSHAPv2 get_asym_state_key", test_get_asym_key);
add_test("MSHAPv2 authenticator_response", test_authenticator_response);
l_test_add("MSHAPv2 nt_password-hash",
test_nt_password_hash, NULL);
l_test_add("MSHAPv2 generate_nt_response",
test_generate_nt_response, NULL);
l_test_add("MSHAPv2 get_master_key",
test_get_master_key, NULL);
l_test_add("MSHAPv2 get_asym_state_key",
test_get_asym_key, NULL);
l_test_add("MSHAPv2 authenticator_response",
test_authenticator_response, NULL);
done:
return l_test_run();
}

View File

@ -3908,6 +3908,38 @@ static void eapol_ap_sta_handshake_ip_alloc_no_req_test(const void *data)
#define _IS_ENABLED2(one_or_two_args) _IS_ENABLED3(one_or_two_args true, false)
#define _IS_ENABLED3(ignore_this, val, ...) val
static bool hash_precheck(const void *data)
{
return (l_checksum_is_supported(L_CHECKSUM_MD5, true) &&
l_checksum_is_supported(L_CHECKSUM_SHA1, true));
}
static bool aes_precheck(const void *data)
{
return (l_cipher_is_supported(L_CIPHER_AES) &&
l_checksum_is_supported(L_CHECKSUM_MD5, true) &&
l_checksum_is_supported(L_CHECKSUM_SHA1, true));
}
static bool pkcs8_precheck(const void *data)
{
return (IS_ENABLED(HAVE_PKCS8_SUPPORT) &&
l_cipher_is_supported(L_CIPHER_AES) &&
l_cipher_is_supported(L_CIPHER_AES_CBC) &&
l_cipher_is_supported(L_CIPHER_DES3_EDE_CBC) &&
l_checksum_is_supported(L_CHECKSUM_MD5, true) &&
l_checksum_is_supported(L_CHECKSUM_SHA1, true) &&
l_key_is_supported(L_KEY_FEATURE_CRYPTO) &&
l_key_is_supported(L_KEY_FEATURE_RESTRICT));
}
#define add_hash_test(name, func, data) l_test_add_data_func_precheck(name, \
data, func, hash_precheck, 0)
#define add_aes_test(name, func, data) l_test_add_data_func_precheck(name, \
data, func, aes_precheck, 0)
#define add_pkcs8_test(name, func, data) l_test_add_data_func_precheck(name, \
data, func, pkcs8_precheck, 0)
int main(int argc, char *argv[])
{
l_test_init(&argc, &argv);
@ -3977,80 +4009,55 @@ int main(int argc, char *argv[])
l_test_add("/EAPoL Key/Key Frame 32",
eapol_key_test, &eapol_key_test_32);
if (!l_checksum_is_supported(L_CHECKSUM_MD5, true) ||
!l_checksum_is_supported(L_CHECKSUM_SHA1, true))
goto done;
l_test_add("/EAPoL Key/MIC Test 1",
add_hash_test("/EAPoL Key/MIC Test 1",
eapol_key_mic_test, &eapol_key_mic_test_1);
l_test_add("/EAPoL Key/MIC Test 2",
add_hash_test("/EAPoL Key/MIC Test 2",
eapol_key_mic_test, &eapol_key_mic_test_2);
l_test_add("/EAPoL Key/Calculate MIC Test 1",
add_hash_test("/EAPoL Key/Calculate MIC Test 1",
eapol_calculate_mic_test, &eapol_calculate_mic_test_1);
if (!l_cipher_is_supported(L_CIPHER_AES))
goto done;
add_aes_test("EAPoL/WPA2 4-Way Handshake",
eapol_4way_test, NULL);
add_aes_test("EAPoL/WPA2 4-Way & GTK Handshake",
eapol_wpa2_handshake_test, NULL);
add_aes_test("EAPoL/WPA 4-Way & GTK Handshake",
eapol_wpa_handshake_test, NULL);
add_aes_test("EAPoL/WPA2 PTK State Machine",
eapol_sm_test_ptk, NULL);
add_aes_test("EAPoL IGTK & 4-Way Handshake",
eapol_sm_test_igtk, NULL);
add_aes_test("EAPoL/WPA2 PTK & GTK State Machine",
eapol_sm_test_wpa2_ptk_gtk, NULL);
add_aes_test("EAPoL/WPA PTK & GTK State Machine Test 1",
eapol_sm_test_wpa_ptk_gtk, NULL);
add_aes_test("EAPoL/WPA PTK & GTK State Machine Test 2",
eapol_sm_test_wpa_ptk_gtk_2, NULL);
add_aes_test("EAPoL/WPA2 Retransmit Test",
eapol_sm_wpa2_retransmit_test, NULL);
l_test_add("EAPoL/WPA2 4-Way Handshake",
&eapol_4way_test, NULL);
add_pkcs8_test("EAPoL/8021x EAP-TLS & 4-Way Handshake",
eapol_sm_test_eap_tls, NULL);
add_pkcs8_test("EAPoL/8021x EAP-TTLS+EAP-MD5 & 4-Way Handshake",
eapol_sm_test_eap_ttls_md5, NULL);
add_pkcs8_test("EAPoL/8021x EAP NAK",
eapol_sm_test_eap_nak, NULL);
add_pkcs8_test("EAPoL/8021x EAP-TLS subject name match",
eapol_sm_test_eap_tls_subject_good, NULL);
add_pkcs8_test("EAPoL/8021x EAP-TLS subject name mismatch",
eapol_sm_test_eap_tls_subject_bad, NULL);
add_pkcs8_test("EAPoL/8021x EAP-TLS embedded certs",
eapol_sm_test_eap_tls_embedded, NULL);
l_test_add("EAPoL/WPA2 4-Way & GTK Handshake",
&eapol_wpa2_handshake_test, NULL);
add_aes_test("EAPoL/FT-Using-PSK 4-Way Handshake",
eapol_ft_handshake_test, NULL);
add_aes_test("EAPoL/Supplicant+Authenticator 4-Way Handshake",
eapol_ap_sta_handshake_test, NULL);
add_aes_test("EAPoL/Supplicant+Authenticator 4-Way Handshake Bad PSK",
eapol_ap_sta_handshake_bad_psk_test, NULL);
add_aes_test("EAPoL/Supplicant+Authenticator IP Allocation OK",
eapol_ap_sta_handshake_ip_alloc_ok_test, NULL);
add_aes_test("EAPoL/Supplicant+Authenticator IP Allocation no request",
eapol_ap_sta_handshake_ip_alloc_no_req_test, NULL);
l_test_add("EAPoL/WPA 4-Way & GTK Handshake",
&eapol_wpa_handshake_test, NULL);
l_test_add("EAPoL/WPA2 PTK State Machine", &eapol_sm_test_ptk, NULL);
l_test_add("EAPoL IGTK & 4-Way Handshake",
&eapol_sm_test_igtk, NULL);
l_test_add("EAPoL/WPA2 PTK & GTK State Machine",
&eapol_sm_test_wpa2_ptk_gtk, NULL);
l_test_add("EAPoL/WPA PTK & GTK State Machine Test 1",
&eapol_sm_test_wpa_ptk_gtk, NULL);
l_test_add("EAPoL/WPA PTK & GTK State Machine Test 2",
&eapol_sm_test_wpa_ptk_gtk_2, NULL);
l_test_add("EAPoL/WPA2 Retransmit Test",
&eapol_sm_wpa2_retransmit_test, NULL);
if (IS_ENABLED(HAVE_PKCS8_SUPPORT) &&
l_cipher_is_supported(L_CIPHER_DES3_EDE_CBC) &&
l_cipher_is_supported(L_CIPHER_AES_CBC) &&
l_key_is_supported(L_KEY_FEATURE_RESTRICT |
L_KEY_FEATURE_CRYPTO)) {
l_test_add("EAPoL/8021x EAP-TLS & 4-Way Handshake",
&eapol_sm_test_eap_tls, NULL);
l_test_add("EAPoL/8021x EAP-TTLS+EAP-MD5 & 4-Way Handshake",
&eapol_sm_test_eap_ttls_md5, NULL);
l_test_add("EAPoL/8021x EAP NAK",
&eapol_sm_test_eap_nak, NULL);
l_test_add("EAPoL/8021x EAP-TLS subject name match",
&eapol_sm_test_eap_tls_subject_good, NULL);
l_test_add("EAPoL/8021x EAP-TLS subject name mismatch",
&eapol_sm_test_eap_tls_subject_bad, NULL);
l_test_add("EAPoL/8021x EAP-TLS embedded certs",
&eapol_sm_test_eap_tls_embedded, NULL);
}
l_test_add("EAPoL/FT-Using-PSK 4-Way Handshake",
&eapol_ft_handshake_test, NULL);
l_test_add("EAPoL/Supplicant+Authenticator 4-Way Handshake",
&eapol_ap_sta_handshake_test, NULL);
l_test_add("EAPoL/Supplicant+Authenticator 4-Way Handshake Bad PSK",
&eapol_ap_sta_handshake_bad_psk_test, NULL);
l_test_add("EAPoL/Supplicant+Authenticator IP Allocation OK",
&eapol_ap_sta_handshake_ip_alloc_ok_test, NULL);
l_test_add("EAPoL/Supplicant+Authenticator IP Allocation no request",
&eapol_ap_sta_handshake_ip_alloc_no_req_test, NULL);
done:
return l_test_run();
}

View File

@ -81,18 +81,20 @@ static const struct hmac_data test_case_2 = {
.hmac = "80070713463e7749b90c2dc24911e275",
};
static bool test_precheck(const void *data)
{
return l_checksum_is_supported(L_CHECKSUM_MD5, true);
}
#define add_test(name, func, data) l_test_add_data_func_precheck(name, data, \
func, test_precheck, 0)
int main(int argc, char *argv[])
{
l_test_init(&argc, &argv);
if (!l_checksum_is_supported(L_CHECKSUM_MD5, true)) {
printf("MD5 support missing, skipping...\n");
goto done;
}
add_test("/hmac-md5/Test case 1", hmac_test, &test_case_1);
add_test("/hmac-md5/Test case 2", hmac_test, &test_case_2);
l_test_add("/hmac-md5/Test case 1", hmac_test, &test_case_1);
l_test_add("/hmac-md5/Test case 2", hmac_test, &test_case_2);
done:
return l_test_run();
}

View File

@ -81,18 +81,20 @@ static const struct hmac_data test_case_2 = {
.hmac = "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9",
};
static bool test_precheck(const void *data)
{
return l_checksum_is_supported(L_CHECKSUM_SHA1, true);
}
#define add_test(name, func, data) l_test_add_data_func_precheck(name, data, \
func, test_precheck, 0)
int main(int argc, char *argv[])
{
l_test_init(&argc, &argv);
if (!l_checksum_is_supported(L_CHECKSUM_SHA1, true)) {
printf("SHA1 support missing, skipping...\n");
goto done;
}
add_test("/hmac-sha1/Test case 1", hmac_test, &test_case_1);
add_test("/hmac-sha1/Test case 2", hmac_test, &test_case_2);
l_test_add("/hmac-sha1/Test case 1", hmac_test, &test_case_1);
l_test_add("/hmac-sha1/Test case 2", hmac_test, &test_case_2);
done:
return l_test_run();
}

View File

@ -83,18 +83,20 @@ static const struct hmac_data test_case_2 = {
"ef4d59a14946175997479dbc2d1a3cd8",
};
static bool test_precheck(const void *data)
{
return l_checksum_is_supported(L_CHECKSUM_SHA256, true);
}
#define add_test(name, func, data) l_test_add_data_func_precheck(name, data, \
func, test_precheck, 0)
int main(int argc, char *argv[])
{
l_test_init(&argc, &argv);
if (!l_checksum_is_supported(L_CHECKSUM_SHA256, true)) {
printf("SHA256 support missing, skipping...\n");
goto done;
}
add_test("/hmac-sha256/Test case 1", hmac_test, &test_case_1);
add_test("/hmac-sha256/Test case 2", hmac_test, &test_case_2);
l_test_add("/hmac-sha256/Test case 1", hmac_test, &test_case_1);
l_test_add("/hmac-sha256/Test case 2", hmac_test, &test_case_2);
done:
return l_test_run();
}

View File

@ -81,17 +81,19 @@ static const struct kdf_data test_case_1 = {
"84f7d2291143d4d4",
};
static bool test_precheck(const void *data)
{
return l_checksum_is_supported(L_CHECKSUM_SHA256, true);
}
#define add_test(name, func, data) l_test_add_data_func_precheck(name, data, \
func, test_precheck, 0)
int main(int argc, char *argv[])
{
l_test_init(&argc, &argv);
if (!l_checksum_is_supported(L_CHECKSUM_SHA256, true)) {
printf("SHA256 support missing, skipping...\n");
goto done;
}
add_test("/kdf-sha256/Test case 1", kdf_test, &test_case_1);
l_test_add("/kdf-sha256/Test case 1", kdf_test, &test_case_1);
done:
return l_test_run();
}

View File

@ -113,19 +113,21 @@ static const struct prf_data test_case_3 = {
"f7b4abd43d87f0a68f1cbd9e2b6f7607",
};
static bool test_precheck(const void *data)
{
return l_checksum_is_supported(L_CHECKSUM_SHA1, true);
}
#define add_test(name, func, data) l_test_add_data_func_precheck(name, data, \
func, test_precheck, 0)
int main(int argc, char *argv[])
{
l_test_init(&argc, &argv);
if (!l_checksum_is_supported(L_CHECKSUM_SHA1, true)) {
printf("SHA1 support missing, skipping...\n");
goto done;
}
add_test("/prf-sha1/Test case 1", prf_test, &test_case_1);
add_test("/prf-sha1/Test case 2", prf_test, &test_case_2);
add_test("/prf-sha1/Test case 3", prf_test, &test_case_3);
l_test_add("/prf-sha1/Test case 1", prf_test, &test_case_1);
l_test_add("/prf-sha1/Test case 2", prf_test, &test_case_2);
l_test_add("/prf-sha1/Test case 3", prf_test, &test_case_3);
done:
return l_test_run();
}

View File

@ -871,32 +871,29 @@ static void test_pt_pwe(const void *data)
l_ecc_point_free(pt);
}
static bool test_precheck(const void *data)
{
return (l_getrandom_is_supported() &&
l_checksum_is_supported(L_CHECKSUM_SHA256, true));
}
#define add_test(name, func) l_test_add_func_precheck(name, func, \
test_precheck, 0)
int main(int argc, char *argv[])
{
l_test_init(&argc, &argv);
if (!l_getrandom_is_supported()) {
l_info("l_getrandom not supported, skipping...");
goto done;
}
add_test("SAE anti-clogging", test_clogging);
add_test("SAE early confirm", test_early_confirm);
add_test("SAE reflection", test_reflection);
add_test("SAE malformed commit", test_malformed_commit);
add_test("SAE malformed confirm", test_malformed_confirm);
add_test("SAE bad group", test_bad_group);
add_test("SAE bad confirm", test_bad_confirm);
add_test("SAE confirm after accept", test_confirm_after_accept);
add_test("SAE end-to-end", test_end_to_end);
add_test("SAE pt-pwe", test_pt_pwe);
if (!l_checksum_is_supported(L_CHECKSUM_SHA256, true)) {
l_info("SHA256/HMAC_SHA256 not supported, skipping...");
goto done;
}
l_test_add("SAE anti-clogging", test_clogging, NULL);
l_test_add("SAE early confirm", test_early_confirm, NULL);
l_test_add("SAE reflection", test_reflection, NULL);
l_test_add("SAE malformed commit", test_malformed_commit, NULL);
l_test_add("SAE malformed confirm", test_malformed_confirm, NULL);
l_test_add("SAE bad group", test_bad_group, NULL);
l_test_add("SAE bad confirm", test_bad_confirm, NULL);
l_test_add("SAE confirm after accept", test_confirm_after_accept, NULL);
l_test_add("SAE end-to-end", test_end_to_end, NULL);
l_test_add("SAE pt-pwe", test_pt_pwe, NULL);
done:
return l_test_run();
}

View File

@ -30,26 +30,37 @@
#include "src/storage.h"
static bool aes_ctr_supported(const void *data)
{
return l_cipher_is_supported(L_CIPHER_AES_CTR);
}
static void test_short_encrypted_bytes(const void *data)
{
struct l_settings *settings = l_settings_new();
bool changed;
int err;
storage_init((const uint8_t *)"abc123", 6);
l_settings_set_string(settings, "Security", "EncryptedSecurity", "012345");
l_settings_set_string(settings, "Security", "EncryptedSalt", "012345");
assert(__storage_decrypt(settings, "mySSID", &changed) < 0);
err = __storage_decrypt(settings, "mySSID", &changed);
assert(err == -EBADMSG);
l_settings_free(settings);
storage_exit();
}
int main(int argc, char *argv[])
{
l_test_init(&argc, &argv);
storage_init((const uint8_t *)"abc123", 6);
l_test_add("/storage/profile encryption",
test_short_encrypted_bytes, NULL);
l_test_add_func_precheck("/storage/profile encryption",
test_short_encrypted_bytes,
aes_ctr_supported, 0);
return l_test_run();
}

View File

@ -2574,6 +2574,40 @@ struct wsc_credential wsc_r_test_open_cred = {
.encryption_type = WSC_ENCRYPTION_TYPE_NONE,
};
static bool getrandom_precheck(const void *data)
{
return l_getrandom_is_supported();
}
static bool aes_cbc_precheck(const void *data)
{
return (l_key_is_supported(L_KEY_FEATURE_DH) &&
l_cipher_is_supported(L_CIPHER_AES_CBC));
}
static bool key_crypto_precheck(const void *data)
{
return (l_key_is_supported(L_KEY_FEATURE_CRYPTO) &&
l_checksum_is_supported(L_CHECKSUM_SHA256, true));
}
static bool key_dh_precheck(const void *data)
{
return (l_key_is_supported(L_KEY_FEATURE_DH) &&
l_key_is_supported(L_KEY_FEATURE_CRYPTO) &&
l_checksum_is_supported(L_CHECKSUM_SHA256, true));
}
#define add_aes_cbc_test(name, func, data) l_test_add_data_func_precheck(name, \
data, func, \
aes_cbc_precheck, 0)
#define add_crypto_test(name, func, data) l_test_add_data_func_precheck(name, \
data, func, \
key_crypto_precheck, 0)
#define add_dh_test(name, func, data) l_test_add_data_func_precheck(name, \
data, func, \
key_dh_precheck, 0)
int main(int argc, char *argv[])
{
l_test_init(&argc, &argv);
@ -2595,8 +2629,8 @@ int main(int argc, char *argv[])
l_test_add("/wsc/pin/valid pin", wsc_test_pin_valid, NULL);
l_test_add("/wsc/pin/valid checksum", wsc_test_pin_checksum, NULL);
if (l_getrandom_is_supported())
l_test_add("/wsc/pin/generate", wsc_test_pin_generate, NULL);
l_test_add_func_precheck("/wsc/pin/generate", wsc_test_pin_generate,
getrandom_precheck, 0);
l_test_add("/wsc/gen_uuid/1", wsc_test_uuid_from_addr,
&uuid_from_addr_data_1);
@ -2607,96 +2641,77 @@ int main(int argc, char *argv[])
l_test_add("/wsc/build/m1 1", wsc_test_build_m1, &m1_data_1);
l_test_add("/wsc/build/m1 2", wsc_test_build_m1, &m1_data_2);
if (!l_checksum_is_supported(L_CHECKSUM_SHA256, true)) {
printf("SHA256 support missing, skipping other tests...\n");
goto done;
}
add_dh_test("/wsc/parse/m2 1", wsc_test_parse_m2, &m2_data_1);
add_dh_test("/wsc/parse/m2 2", wsc_test_parse_m2, &m2_data_2);
if (!l_key_is_supported(L_KEY_FEATURE_CRYPTO)) {
printf("Key crypto not supported, skipping other tests...\n");
goto done;
}
add_crypto_test("/wsc/build/m2 1", wsc_test_build_m2, &m2_data_1);
if (l_key_is_supported(L_KEY_FEATURE_DH)) {
l_test_add("/wsc/parse/m2 1", wsc_test_parse_m2, &m2_data_1);
l_test_add("/wsc/parse/m2 2", wsc_test_parse_m2, &m2_data_2);
}
add_crypto_test("/wsc/parse/m3 1", wsc_test_parse_m3, &m3_data_1);
add_crypto_test("/wsc/build/m3 1", wsc_test_build_m3, &m3_data_1);
l_test_add("/wsc/build/m2 1", wsc_test_build_m2, &m2_data_1);
add_crypto_test("/wsc/parse/m4 1", wsc_test_parse_m4, &m4_data_1);
add_crypto_test("/wsc/build/m4 1", wsc_test_build_m4, &m4_data_1);
l_test_add("/wsc/parse/m3 1", wsc_test_parse_m3, &m3_data_1);
l_test_add("/wsc/build/m3 1", wsc_test_build_m3, &m3_data_1);
add_crypto_test("/wsc/parse/m4 encrypted settings 1",
wsc_test_parse_m4_encrypted_settings,
&m4_encrypted_settings_data_1);
add_crypto_test("/wsc/build/m4 encrypted settings 1",
wsc_test_build_m4_encrypted_settings,
&m4_encrypted_settings_data_1);
l_test_add("/wsc/parse/m4 1", wsc_test_parse_m4, &m4_data_1);
l_test_add("/wsc/build/m4 1", wsc_test_build_m4, &m4_data_1);
add_crypto_test("/wsc/parse/m5 1", wsc_test_parse_m5, &m5_data_1);
add_crypto_test("/wsc/build/m5 1", wsc_test_build_m5, &m5_data_1);
l_test_add("/wsc/parse/m4 encrypted settings 1",
wsc_test_parse_m4_encrypted_settings,
&m4_encrypted_settings_data_1);
l_test_add("/wsc/build/m4 encrypted settings 1",
wsc_test_build_m4_encrypted_settings,
&m4_encrypted_settings_data_1);
add_crypto_test("/wsc/parse/m6 1", wsc_test_parse_m6, &m6_data_1);
add_crypto_test("/wsc/build/m6 1", wsc_test_build_m6, &m6_data_1);
l_test_add("/wsc/parse/m5 1", wsc_test_parse_m5, &m5_data_1);
l_test_add("/wsc/build/m5 1", wsc_test_build_m5, &m5_data_1);
add_crypto_test("/wsc/parse/m6 encrypted settings 1",
wsc_test_parse_m6_encrypted_settings,
&m6_encrypted_settings_data_1);
add_crypto_test("/wsc/build/m6 encrypted settings 1",
wsc_test_build_m6_encrypted_settings,
&m6_encrypted_settings_data_1);
l_test_add("/wsc/parse/m6 1", wsc_test_parse_m6, &m6_data_1);
l_test_add("/wsc/build/m6 1", wsc_test_build_m6, &m6_data_1);
add_crypto_test("/wsc/parse/m7 1", wsc_test_parse_m7, &m7_data_1);
add_crypto_test("/wsc/build/m7 1", wsc_test_build_m7, &m7_data_1);
l_test_add("/wsc/parse/m6 encrypted settings 1",
wsc_test_parse_m6_encrypted_settings,
&m6_encrypted_settings_data_1);
l_test_add("/wsc/build/m6 encrypted settings 1",
wsc_test_build_m6_encrypted_settings,
&m6_encrypted_settings_data_1);
add_crypto_test("/wsc/parse/m8 1", wsc_test_parse_m8, &m8_data_1);
add_crypto_test("/wsc/build/m8 1", wsc_test_build_m8, &m8_data_1);
l_test_add("/wsc/parse/m7 1", wsc_test_parse_m7, &m7_data_1);
l_test_add("/wsc/build/m7 1", wsc_test_build_m7, &m7_data_1);
add_crypto_test("/wsc/parse/m8 encrypted settings 1",
wsc_test_parse_m8_encrypted_settings,
&m8_encrypted_settings_data_1);
add_crypto_test("/wsc/build/m8 encrypted settings 1",
wsc_test_build_m8_encrypted_settings,
&m8_encrypted_settings_data_1);
l_test_add("/wsc/parse/m8 1", wsc_test_parse_m8, &m8_data_1);
l_test_add("/wsc/build/m8 1", wsc_test_build_m8, &m8_data_1);
l_test_add("/wsc/parse/m8 encrypted settings 1",
wsc_test_parse_m8_encrypted_settings,
&m8_encrypted_settings_data_1);
l_test_add("/wsc/build/m8 encrypted settings 1",
wsc_test_build_m8_encrypted_settings,
&m8_encrypted_settings_data_1);
l_test_add("/wsc/parse/wsc_done 1", wsc_test_parse_wsc_done,
add_crypto_test("/wsc/parse/wsc_done 1", wsc_test_parse_wsc_done,
&wsc_done_data_1);
l_test_add("/wsc/build/wsc_done 1", wsc_test_build_wsc_done,
add_crypto_test("/wsc/build/wsc_done 1", wsc_test_build_wsc_done,
&wsc_done_data_1);
if (!l_key_is_supported(L_KEY_FEATURE_DH))
goto done;
l_test_add("/wsc/diffie-hellman/generate pubkey 1",
add_dh_test("/wsc/diffie-hellman/generate pubkey 1",
wsc_test_dh_generate_pubkey,
&dh_generate_pubkey_test_data_1);
l_test_add("/wsc/diffie-hellman/generate pubkey 2",
add_dh_test("/wsc/diffie-hellman/generate pubkey 2",
wsc_test_dh_generate_pubkey,
&dh_generate_pubkey_test_data_2);
if (!l_cipher_is_supported(L_CIPHER_AES_CBC))
goto done;
l_test_add("/wsc/handshake/PBC Handshake Test",
add_aes_cbc_test("/wsc/handshake/PBC Handshake Test",
wsc_test_pbc_handshake, NULL);
l_test_add("/wsc/retransmission/no fragmentation",
add_aes_cbc_test("/wsc/retransmission/no fragmentation",
wsc_test_retransmission_no_fragmentation, NULL);
l_test_add("/wsc-r/handshake/PBC Handshake WPA2 passphrase test",
wsc_r_test_pbc_handshake,
&wsc_r_test_wpa2_cred_passphrase);
l_test_add("/wsc-r/handshake/PBC Handshake WPA2 PSK test",
wsc_r_test_pbc_handshake,
&wsc_r_test_wpa2_cred_psk);
l_test_add("/wsc-r/handshake/PBC Handshake Open test",
wsc_r_test_pbc_handshake,
&wsc_r_test_open_cred);
add_aes_cbc_test("/wsc-r/handshake/PBC Handshake WPA2 passphrase test",
wsc_r_test_pbc_handshake,
&wsc_r_test_wpa2_cred_passphrase);
add_aes_cbc_test("/wsc-r/handshake/PBC Handshake WPA2 PSK test",
wsc_r_test_pbc_handshake,
&wsc_r_test_wpa2_cred_psk);
add_aes_cbc_test("/wsc-r/handshake/PBC Handshake Open test",
wsc_r_test_pbc_handshake,
&wsc_r_test_open_cred);
done:
return l_test_run();
}