diff --git a/repos/dde_linux/lib/mk/wpa_supplicant.mk b/repos/dde_linux/lib/mk/wpa_supplicant.mk
index eef1413562..3fe6593f26 100644
--- a/repos/dde_linux/lib/mk/wpa_supplicant.mk
+++ b/repos/dde_linux/lib/mk/wpa_supplicant.mk
@@ -44,7 +44,8 @@ INC_DIR += $(WS_CONTRIB_DIR)/wpa_supplicant
CC_OPT += -DCONFIG_BACKEND_FILE -DCONFIG_NO_CONFIG_WRITE \
-DCONFIG_SME -DCONFIG_CTRL_IFACE \
-DCONFIG_BGSCAN -DCONFIG_BGSCAN_SIMPLE \
- -DCONFIG_OPENSSL_CMAC -DCONFIG_SHA256
+ -DCONFIG_OPENSSL_CMAC -DCONFIG_SHA256 \
+ -DCONFIG_SAE -DCONFIG_ECC
CC_OPT += -DTLS_DEFAULT_CIPHERS=\"DEFAULT:!EXP:!LOW\"
@@ -52,17 +53,19 @@ INC_DIR += $(WS_CONTRIB_DIR)/src/
# common
SRC_C_common = ieee802_11_common.c wpa_common.c hw_features_common.c \
- ctrl_iface_common.c
+ ctrl_iface_common.c sae.c dragonfly.c
SRC_C += $(addprefix src/common/, $(SRC_C_common))
INC_DIR += $(WS_CONTRIB_DIR)/src/common
# crypto
SRC_C_crypto = crypto_openssl.c \
+ dh_groups.c \
ms_funcs.c \
random.c \
sha1-prf.c \
sha1-tlsprf.c \
sha256-prf.c \
+ sha256-kdf.c \
tls_openssl.c
SRC_C += $(addprefix src/crypto/, $(SRC_C_crypto))
INC_DIR += $(WS_CONTRIB_DIR)/src/crypto
diff --git a/repos/dde_linux/src/drivers/wifi/README b/repos/dde_linux/src/drivers/wifi/README
index f1f9503b84..e583824999 100644
--- a/repos/dde_linux/src/drivers/wifi/README
+++ b/repos/dde_linux/src/drivers/wifi/README
@@ -89,8 +89,9 @@ connect to a network:
To temporarily prevent any radio activity, the 'rfkill' attribute
can be set to 'true'.
-If the network is protected by, e.g., WPA/WPA2, the protection type, either
-'WPA' or 'WPA2' as well as the the passphrase have to be specified.
+If the network is protected by, e.g., WPA/WPA2/WPA3, the protection type,
+either 'WPA', 'WPA2' or 'WPA3' as well as the the passphrase have to be
+specified.
The 'bssid' attribute can be used to select a specifc accesspoint within a
network. Of all attributes only the 'ssid' attribute is mandatory, all others
are optional and should only be used when needed.
@@ -150,9 +151,9 @@ the 'rfkill' attribute.
By subscribing to both reports and providing the required 'wifi_config' ROM
module, a component is able control the wireless driver.
-Currently only WPA/WPA2 protection using a passphrase is supported and the the
-SSID is copied verbatim. At the moment, there is no way to express or escape
-non alphanumeric characters.
+Currently only WPA/WPA2/WPA3 protection using a passphrase is supported and
+the SSID is copied verbatim. At the moment, there is no way to express or
+escape non alphanumeric characters.
The driver optionally reports the following information under the
label "devices" if requested in the config as depicted.
diff --git a/repos/dde_linux/src/drivers/wifi/frontend.h b/repos/dde_linux/src/drivers/wifi/frontend.h
index 6460516adf..d296e01124 100644
--- a/repos/dde_linux/src/drivers/wifi/frontend.h
+++ b/repos/dde_linux/src/drivers/wifi/frontend.h
@@ -185,6 +185,7 @@ struct Accesspoint : Genode::Interface
bool valid() const { return ssid.length() > 1; }
bool bssid_valid() const { return bssid.length() > 1; }
bool wpa() const { return prot != "NONE"; }
+ bool wpa3() const { return prot == "WPA3"; }
bool stored() const { return id != -1; }
};
@@ -233,11 +234,13 @@ static void for_each_result_line(char const *msg, FUNC const &func)
bool const is_wpa1 = Util::string_contains((char const*)s[3], "WPA");
bool const is_wpa2 = Util::string_contains((char const*)s[3], "WPA2");
+ bool const is_wpa3 = Util::string_contains((char const*)s[3], "SAE");
unsigned signal = Util::approximate_quality(s[2]);
char const *prot = is_wpa1 ? "WPA" : "NONE";
prot = is_wpa2 ? "WPA2" : prot;
+ prot = is_wpa3 ? "WPA3" : prot;
Accesspoint ap(s[0], s[1], prot, s[4], signal);
@@ -556,14 +559,16 @@ struct Wifi::Frontend : Wifi::Rfkill_notification_handler
INITIATE_SCAN = 0x00|SCAN,
PENDING_RESULTS = 0x10|SCAN,
- ADD_NETWORK = 0x00|NETWORK,
- FILL_NETWORK_SSID = 0x10|NETWORK,
- FILL_NETWORK_BSSID = 0x20|NETWORK,
- FILL_NETWORK_PSK = 0x30|NETWORK,
- REMOVE_NETWORK = 0x40|NETWORK,
- ENABLE_NETWORK = 0x50|NETWORK,
- DISABLE_NETWORK = 0x60|NETWORK,
- LIST_NETWORKS = 0x80|NETWORK,
+ ADD_NETWORK = 0x00|NETWORK,
+ FILL_NETWORK_SSID = 0x10|NETWORK,
+ FILL_NETWORK_BSSID = 0x20|NETWORK,
+ FILL_NETWORK_KEY_MGMT = 0x30|NETWORK,
+ FILL_NETWORK_PSK = 0x40|NETWORK,
+ REMOVE_NETWORK = 0x50|NETWORK,
+ ENABLE_NETWORK = 0x60|NETWORK,
+ DISABLE_NETWORK = 0x70|NETWORK,
+ LIST_NETWORKS = 0x90|NETWORK,
+ SET_NETWORK_PMF = 0xA0|NETWORK,
CONNECTING = 0x00|CONNECT,
CONNECTED = 0x10|CONNECT,
@@ -581,6 +586,7 @@ struct Wifi::Frontend : Wifi::Rfkill_notification_handler
case ADD_NETWORK: return "add network";
case FILL_NETWORK_SSID: return "fill network ssid";
case FILL_NETWORK_BSSID: return "fill network bssid";
+ case FILL_NETWORK_KEY_MGMT: return "fill network key_mgmt";
case FILL_NETWORK_PSK: return "fill network pass";
case REMOVE_NETWORK: return "remove network";
case ENABLE_NETWORK: return "enable network";
@@ -591,6 +597,7 @@ struct Wifi::Frontend : Wifi::Rfkill_notification_handler
case STATUS: return "status";
case LIST_NETWORKS: return "list networks";
case INFO: return "info";
+ case SET_NETWORK_PMF: return "set network pmf";
default: return "unknown";
};
}
@@ -922,6 +929,18 @@ struct Wifi::Frontend : Wifi::Rfkill_notification_handler
" bssid ", bssid));
}
+ void _network_set_key_mgmt_sae()
+ {
+ _submit_cmd(Cmd_str("SET_NETWORK ", _processed_ap->id,
+ " key_mgmt SAE"));
+ }
+
+ void _network_set_pmf()
+ {
+ _submit_cmd(Cmd_str("SET_NETWORK ", _processed_ap->id,
+ " ieee80211w 2"));
+ }
+
void _network_set_psk()
{
if (_processed_ap->wpa()) {
@@ -1018,6 +1037,41 @@ struct Wifi::Frontend : Wifi::Rfkill_notification_handler
_state_transition(_state, State::IDLE);
} else {
+ /*
+ * For the moment branch here to handle WPA3-personal-only
+ * explicitly.
+ */
+ if (_processed_ap->wpa3()) {
+ _state_transition(_state, State::FILL_NETWORK_KEY_MGMT);
+ _network_set_key_mgmt_sae();
+ } else {
+ _state_transition(_state, State::FILL_NETWORK_PSK);
+ _network_set_psk();
+ }
+
+ successfully = true;
+ }
+ break;
+ case State::FILL_NETWORK_KEY_MGMT:
+ _state_transition(_state, State::IDLE);
+
+ if (!cmd_successful(msg)) {
+ Genode::error("could not set key_mgmt for network: ", msg);
+ _state_transition(_state, State::IDLE);
+ } else {
+ _state_transition(_state, State::SET_NETWORK_PMF);
+ _network_set_pmf();
+
+ successfully = true;
+ }
+ break;
+ case State::SET_NETWORK_PMF:
+ _state_transition(_state, State::IDLE);
+
+ if (!cmd_successful(msg)) {
+ Genode::error("could not set PMF for network: ", msg);
+ _state_transition(_state, State::IDLE);
+ } else {
_state_transition(_state, State::FILL_NETWORK_PSK);
_network_set_psk();
diff --git a/repos/pc/run/pc_wifi.run b/repos/pc/run/pc_wifi.run
index 92b9af7dde..f27498c8c5 100644
--- a/repos/pc/run/pc_wifi.run
+++ b/repos/pc/run/pc_wifi.run
@@ -17,6 +17,13 @@ proc wifi_psk { } {
return $::env(GENODE_WIFI_PSK)
}
+proc wifi_wpa { } {
+ if {![info exists ::env(GENODE_WIFI_WPA)]} {
+ return WPA2
+ }
+ return $::env(GENODE_WIFI_WPA)
+}
+
#
# widi_drv config generator (supporting a network list)
#
@@ -232,15 +239,15 @@ append config {
-} [wifi_config 30 5 no [list "[wifi_ssid] WPA2 [wifi_psk] yes"]] {
+} [wifi_config 30 5 no [list "[wifi_ssid] [wifi_wpa] [wifi_psk] yes"]] {
-} [wifi_config 30 5 yes [list "[wifi_ssid] WPA2 [wifi_psk] yes"]] {
+} [wifi_config 30 5 yes [list "[wifi_ssid] [wifi_wpa] [wifi_psk] yes"]] {
-} [wifi_config 30 5 no [list "[wifi_ssid] WPA2 [wifi_psk] yes"]] {
+} [wifi_config 30 5 no [list "[wifi_ssid] [wifi_wpa] [wifi_psk] yes"]] {