3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2025-06-30 18:57:25 +02:00

Compare commits

..

37 Commits
3.6 ... 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
Marcel Holtmann
36b1086f60 Release 3.7 2025-05-04 19:34:32 +02:00
Marcel Holtmann
266eb405f2 build: Add test-storage to ignore list 2025-05-04 19:34:15 +02:00
James Prestwood
0a8e646231 eap: initialize vendor_id/vendor_type to zero
This fixes a compiler warning, specifically on ARM/GCC 12.2.0

src/eap.c: In function ‘eap_rx_packet’:
src/eap.c:419:57: error: ‘vendor_type’ may be used uninitialized [-Werror=maybe-uninitialized]
  419 |         (type == EAP_TYPE_EXPANDED && vendor_id == (id) && vendor_type == (t))
      |                                                         ^~
src/eap.c:429:18: note: ‘vendor_type’ was declared here
  429 |         uint32_t vendor_type;
      |                  ^~~~~~~~~~~
src/eap.c:419:49: error: ‘vendor_id’ may be used uninitialized [-Werror=maybe-uninitialized]
  419 |         (type == EAP_TYPE_EXPANDED && vendor_id == (id) && vendor_type == (t))
      |                                                 ^~
src/eap.c:428:18: note: ‘vendor_id’ was declared here
  428 |         uint32_t vendor_id;
      |                  ^~~~~~~~~
2025-05-02 12:14:37 -05:00
James Prestwood
8ebc4780ea station: fix setting an empty affinities list
A prior patch broke this by checking the return of
l_dbus_message_iter_next_entry. This was really subtle but the logic
actually relied on _not_ checking that return in order to handle
empty lists.

Instead of reverting the logic was adapted/commented to make it more
clear what the API expects from DBus. If list contains at least one
value the first element path will get set, if it contains zero
values "new_path" will be set to NULL which will then cause the
list to be cleared later on.

This both fixes the regression, and makes it clear that a zero
element list is supported and handled.
2025-04-23 09:42:48 -05:00
Marcel Holtmann
4ded663e68 unit: Fix country code assignment for test case
CC       unit/test-p2p.o
unit/test-p2p.c:344:36: error: initializer-string for array of ‘char’ truncates NUL terminator but destination lacks ‘nonstring’ attribute (4 chars into 3 available) [-Werror=unterminated-string-initialization]
  344 |                         .country = "XX\x04",
      |                                    ^~~~~~~~
2025-04-19 22:49:53 +02:00
James Prestwood
c00bc3a065 eap-mschapv2: Fix leak of state->user on error path
Fixes: 6dc5d2c3ecb6 ("eap-mschapv2: Load credentials obtained from agent")
2025-04-16 14:58:00 -05:00
James Prestwood
f469db8a95 station: check return when advancing iterator
Fixes: f4ec1ee509fc ("station: add Affinities DBus property")
2025-04-16 14:58:00 -05:00
James Prestwood
c3a27354ff unit: add test-storage
For now, a single test for __storage_decrypt that ensures an
invalid length fails as expected.
2025-04-16 14:58:00 -05:00
James Prestwood
d927fd07c1 storage: add length check in __storage_decrypt
The length of EncryptedSecurity was assumed to be at least 16 bytes
and anything less would underflow the length to l_malloc.

Fixes: 01cd8587606b ("storage: implement network profile encryption")
2025-04-16 14:58:00 -05:00
James Prestwood
8dff156eb6 monitor: add size check for interworking IE parsing
Fixes: e0c9b68467fa ("monitor: parse/print HS2.0/WFA IEs")
2025-04-16 14:58:00 -05:00
James Prestwood
e5c41a8024 unit: add test for duplicate URI elements 2025-04-16 14:58:00 -05:00
James Prestwood
603d6b2881 dpp-util: fail on duplicate values in URI
The MAC and version elements weren't super critical but the channel
and bootstrapping key elements would result in memory leaks if there
were duplicates.

This patch now will not allow duplicate elements in the URI.

Fixes: f7f602e1b1e7 ("dpp-util: add URI parsing")
2025-04-16 14:58:00 -05:00
James Prestwood
d1aa4009bc scan: fix out of bound array access for survey results
The survey arrays were exactly the number of valid channels for a
given band (e.g. 14 for 2.4GHz) but since channels start at 1 this
means that the last channel for a band would overflow the array.

Fixes: 35808debaefd ("scan: use GET_SURVEY for SNR calculation in ranking")
2025-04-16 14:58:00 -05:00
James Prestwood
3c5081c7a6 monitor: fix spelling Exausted -> Exhausted
Caught by codespell

Fixes: 83a2457550e7 ("monitor: add support for limiting PCAP size/count")
2025-04-16 14:58:00 -05:00
41 changed files with 768 additions and 404 deletions

1
.gitignore vendored
View File

@ -68,6 +68,7 @@ unit/test-dpp
unit/test-json
unit/test-nl80211util
unit/test-pmksa
unit/test-storage
unit/cert-*.pem
unit/cert-*.csr
unit/cert-*.srl

View File

@ -1,3 +1,18 @@
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.
Fix issue with handling survey scanning results.
Fix issue with handling duplicate values in DPP URI.
ver 3.6:
Fix issue with handling blacklisting and roaming requests.
Fix issue with handling CQM thresholds for FullMAC devices.

View File

@ -441,7 +441,7 @@ unit_tests += unit/test-cmac-aes \
unit/test-arc4 unit/test-wsc unit/test-eap-mschapv2 \
unit/test-eap-sim unit/test-sae unit/test-p2p unit/test-band \
unit/test-dpp unit/test-json unit/test-nl80211util \
unit/test-pmksa
unit/test-pmksa unit/test-storage
endif
if CLIENT
@ -605,6 +605,11 @@ unit_test_nl80211util_LDADD = $(ell_ldadd)
unit_test_pmksa_SOURCES = unit/test-pmksa.c src/pmksa.c src/pmksa.h \
src/module.h src/util.h
unit_test_pmksa_LDADD = $(ell_ldadd)
unit_test_storage_SOURCES = unit/test-storage.c src/storage.c src/storage.h \
src/crypto.c src/crypto.h \
src/common.c src/common.h
unit_test_storage_LDADD = $(ell_ldadd)
endif
if CLIENT

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.6])
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

@ -1915,7 +1915,7 @@ static void print_ie_interworking(unsigned int level,
size--;
ptr++;
if (!size)
if (size < 2)
return;
/*
@ -7433,7 +7433,7 @@ static bool check_pcap(struct nlmon *nlmon, size_t next_size)
pcap_close(nlmon->pcap);
/* Exausted the single PCAP file */
/* Exhausted the single PCAP file */
if (nlmon->max_files < 2) {
printf("Reached maximum size of PCAP, exiting\n");
nlmon->pcap = NULL;

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

@ -1166,21 +1166,34 @@ struct dpp_uri_info *dpp_parse_uri(const char *uri)
switch (*pos) {
case 'C':
if (L_WARN_ON(info->freqs))
goto free_info;
info->freqs = dpp_parse_class_and_channel(pos + 2, len);
if (!info->freqs)
goto free_info;
break;
case 'M':
if (L_WARN_ON(!l_memeqzero(info->mac,
sizeof(info->mac))))
goto free_info;
ret = dpp_parse_mac(pos + 2, len, info->mac);
if (ret < 0)
goto free_info;
break;
case 'V':
if (L_WARN_ON(info->version != 0))
goto free_info;
ret = dpp_parse_version(pos + 2, len, &info->version);
if (ret < 0)
goto free_info;
break;
case 'K':
if (L_WARN_ON(info->boot_public))
goto free_info;
info->boot_public = dpp_parse_key(pos + 2, len);
if (!info->boot_public)
goto free_info;

View File

@ -544,7 +544,8 @@ static bool eap_mschapv2_load_settings(struct eap_state *eap,
return true;
error:
free(state);
l_free(state->user);
l_free(state);
return false;
}

View File

@ -425,8 +425,8 @@ static void eap_handle_response(struct eap_state *eap, const uint8_t *pkt,
size_t len)
{
enum eap_type type;
uint32_t vendor_id;
uint32_t vendor_type;
uint32_t vendor_id = 0;
uint32_t vendor_type = 0;
enum eap_type our_type = eap->method->request_type;
uint32_t our_vendor_id = (eap->method->vendor_id[0] << 16) |
(eap->method->vendor_id[1] << 8) |

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

@ -143,9 +143,9 @@ struct scan_survey {
};
struct scan_survey_results {
struct scan_survey survey_2_4[14];
struct scan_survey survey_5[196];
struct scan_survey survey_6[233];
struct scan_survey survey_2_4[15];
struct scan_survey survey_5[197];
struct scan_survey survey_6[234];
};
struct scan_results {

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
@ -4815,7 +4822,7 @@ static struct l_dbus_message *station_property_set_affinities(
struct l_dbus_message_iter array;
const char *sender = l_dbus_message_get_sender(message);
char *old_path = l_queue_peek_head(station->affinities);
const char *new_path = NULL;
const char *new_path;
struct scan_bss *new_bss = NULL;
struct scan_bss *old_bss = NULL;
bool lower_threshold = false;
@ -4835,10 +4842,15 @@ static struct l_dbus_message *station_property_set_affinities(
if (!l_dbus_message_iter_get_variant(new_value, "ao", &array))
return dbus_error_invalid_args(message);
/* Get first entry, there should be only one */
l_dbus_message_iter_next_entry(&array, &new_path);
/* Get first entry, or if an empty array set the path to NULL */
if (!l_dbus_message_iter_next_entry(&array, &new_path))
new_path = NULL;
if (l_dbus_message_iter_next_entry(&array, &new_path))
/*
* Only allowing single values for now. If there is more than a single
* value, fail
*/
if (new_path && l_dbus_message_iter_next_entry(&array, &new_path))
return dbus_error_invalid_args(message);
old_path = l_queue_peek_head(station->affinities);

View File

@ -500,6 +500,13 @@ int __storage_decrypt(struct l_settings *settings, const char *ssid,
return 0;
}
/*
* It should likely be far larger than this, but that will get caught
* later when reloading the decrypted data.
*/
if (elen < 16)
return -EBADMSG;
/*
* AES-SIV automatically verifies the IV (16 bytes) and returns only
* the decrypted data portion. We add one here for the NULL terminator

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

@ -116,6 +116,29 @@ struct dpp_test_info bad_channels[] = {
},
};
struct dpp_test_info duplicates[] = {
/* Duplicate key */
{
.uri = "DPP:K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADURzxmttZoIRIPWGoQMV00XHWCAQIhXruVWOz0NjlkIA=;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADURzxmttZoIRIPWGoQMV00XHWCAQIhXruVWOz0NjlkIA=;;",
.expect_fail = true
},
/* Duplicate frequencies*/
{
.uri = "DPP:C:81/1,115/36;C:81/1,115/36;;",
.expect_fail = true
},
/* Duplicate MACs*/
{
.uri = "DPP:M:5254005828e5;M:5254005828e5;;",
.expect_fail = true
},
/* Duplicate versions */
{
.uri = "DPP:V:2;V:2;;",
.expect_fail = true
},
};
static bool verify_info(const struct dpp_uri_info *parsed,
const struct dpp_test_info *result)
{
@ -158,6 +181,14 @@ static void test_bad_channels(const void *data)
test_uri_parse(&bad_channels[i]);
}
static void test_duplicate_in_uri(const void *data)
{
unsigned int i;
for (i = 0; i < L_ARRAY_SIZE(duplicates); i++)
test_uri_parse(&duplicates[i]);
}
struct dpp_test_vector {
/* Initiator values */
const char *i_proto_public;
@ -546,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);
@ -576,6 +610,7 @@ int main(int argc, char *argv[])
l_test_add("DPP URI bad key", test_uri_parse, &bad_key);
l_test_add("DPP URI bad channels", test_bad_channels, &bad_channels);
l_test_add("DPP URI unexpected ID", test_uri_parse, &unexpected_id);
l_test_add("DPP URI duplicates", test_duplicate_in_uri, &duplicates);
return l_test_run();
}

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

@ -341,7 +341,7 @@ static const struct p2p_probe_req_data p2p_probe_req_data_1 = {
.group_caps = 0,
},
.listen_channel = {
.country = "XX\x04",
.country = { 'X', 'X', '\x04' },
.oper_class = 81,
.channel_num = 1,
},

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();
}

66
unit/test-storage.c Normal file
View File

@ -0,0 +1,66 @@
/*
*
* Wireless daemon for Linux
*
* Copyright (C) 2025 Locus Robotics. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <assert.h>
#include <ell/ell.h>
#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");
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);
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();
}