mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-26 10:39:23 +01:00
netdev: implement netdev_set_pmk
The 8021x offloading procedure still does EAP in userspace which negotiates the PMK. The kernel then expects to obtain this PMK from userspace by calling SET_PMK. This then allows the firmware to begin the 4-way handshake. Using __eapol_install_set_pmk_func to install netdev_set_pmk, netdev now gets called into once EAP finishes and can begin the final userspace actions prior to the firmware starting the 4-way handshake: - SET_PMK using PMK negotiated with EAP - Emit SETTING_KEYS event - netdev_connect_ok One thing to note is that the kernel provides no way of knowing if the 4-way handshake completed. Assuming SET_PMK/SET_STATION come back with no errors, IWD assumes the PMK was valid. If not, or due to some other issue in the 4-way, the kernel will send a disconnect.
This commit is contained in:
parent
026ec40e1c
commit
379ec4b952
55
src/netdev.c
55
src/netdev.c
@ -83,6 +83,7 @@ struct netdev_handshake_state {
|
||||
uint32_t group_new_key_cmd_id;
|
||||
uint32_t group_management_new_key_cmd_id;
|
||||
uint32_t set_station_cmd_id;
|
||||
uint32_t set_pmk_cmd_id;
|
||||
bool ptk_installed;
|
||||
bool gtk_installed;
|
||||
bool igtk_installed;
|
||||
@ -252,6 +253,11 @@ static void netdev_handshake_state_cancel_all(
|
||||
l_genl_family_cancel(nl80211, nhs->set_station_cmd_id);
|
||||
nhs->set_station_cmd_id = 0;
|
||||
}
|
||||
|
||||
if (nhs->set_pmk_cmd_id) {
|
||||
l_genl_family_cancel(nl80211, nhs->set_pmk_cmd_id);
|
||||
nhs->set_pmk_cmd_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void netdev_handshake_state_free(struct handshake_state *hs)
|
||||
@ -1705,6 +1711,54 @@ invalid_key:
|
||||
netdev_setting_keys_failed(nhs, err);
|
||||
}
|
||||
|
||||
static void netdev_set_pmk_cb(struct l_genl_msg *msg, void *user_data)
|
||||
{
|
||||
struct netdev_handshake_state *nhs = user_data;
|
||||
struct netdev *netdev = nhs->netdev;
|
||||
int err = l_genl_msg_get_error(msg);
|
||||
|
||||
nhs->set_pmk_cmd_id = 0;
|
||||
|
||||
if (err < 0) {
|
||||
l_error("Error with SET_PMK/SET_STATION");
|
||||
netdev_setting_keys_failed(nhs, err);
|
||||
return;
|
||||
}
|
||||
|
||||
handshake_event(netdev->handshake, HANDSHAKE_EVENT_SETTING_KEYS);
|
||||
netdev_connect_ok(netdev);
|
||||
}
|
||||
|
||||
static void netdev_set_pmk(struct handshake_state *hs, const uint8_t *pmk,
|
||||
size_t pmk_len)
|
||||
{
|
||||
struct l_genl_msg *msg;
|
||||
struct netdev_handshake_state *nhs = l_container_of(hs,
|
||||
struct netdev_handshake_state, super);
|
||||
struct netdev *netdev = nhs->netdev;
|
||||
|
||||
/* Only relevent for 8021x offload */
|
||||
if (nhs->type != CONNECTION_TYPE_8021X_OFFLOAD)
|
||||
return;
|
||||
|
||||
msg = l_genl_msg_new(NL80211_CMD_SET_PMK);
|
||||
|
||||
l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index);
|
||||
l_genl_msg_append_attr(msg, NL80211_ATTR_MAC, 6, netdev->handshake->aa);
|
||||
l_genl_msg_append_attr(msg, NL80211_ATTR_PMK,
|
||||
netdev->handshake->pmk_len,
|
||||
netdev->handshake->pmk);
|
||||
|
||||
nhs->set_pmk_cmd_id = l_genl_family_send(nl80211, msg,
|
||||
netdev_set_pmk_cb,
|
||||
nhs, NULL);
|
||||
if (!nhs->set_pmk_cmd_id) {
|
||||
l_error("Failed to set SET_PMK");
|
||||
netdev_setting_keys_failed(nhs, -EIO);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void netdev_handshake_failed(struct handshake_state *hs, uint16_t reason_code)
|
||||
{
|
||||
struct netdev_handshake_state *nhs =
|
||||
@ -5566,6 +5620,7 @@ static int netdev_init(void)
|
||||
|
||||
__eapol_set_rekey_offload_func(netdev_set_rekey_offload);
|
||||
__eapol_set_tx_packet_func(netdev_control_port_frame);
|
||||
__eapol_set_install_pmk_func(netdev_set_pmk);
|
||||
|
||||
unicast_watch = l_genl_add_unicast_watch(genl, NL80211_GENL_NAME,
|
||||
netdev_unicast_notify,
|
||||
|
Loading…
Reference in New Issue
Block a user