mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2025-03-03 06:00:43 +01:00
netdev: add FILS support
From netdev's prospective FILS works the same as OWE/SAE where we create a fils_sm and forward all auth/assoc frames into the FILS module. The only real difference is we do not start EAPoL once FILS completes.
This commit is contained in:
parent
73c9a126bd
commit
b125976fea
110
src/netdev.c
110
src/netdev.c
@ -59,6 +59,7 @@
|
||||
#include "src/sae.h"
|
||||
#include "src/nl80211util.h"
|
||||
#include "src/owe.h"
|
||||
#include "src/fils.h"
|
||||
|
||||
#ifndef ENOTSUPP
|
||||
#define ENOTSUPP 524
|
||||
@ -96,6 +97,7 @@ struct netdev {
|
||||
struct eapol_sm *sm;
|
||||
struct sae_sm *sae_sm;
|
||||
struct owe_sm *owe;
|
||||
struct fils_sm *fils;
|
||||
struct handshake_state *handshake;
|
||||
uint32_t connect_cmd_id;
|
||||
uint32_t disconnect_cmd_id;
|
||||
@ -2366,7 +2368,7 @@ static void netdev_authenticate_event(struct l_genl_msg *msg,
|
||||
* the FT Associate command is included in the attached frame and is
|
||||
* not available in the Authenticate command callback.
|
||||
*/
|
||||
if (!netdev->in_ft && !netdev->sae_sm && !netdev->owe)
|
||||
if (!netdev->in_ft && !netdev->sae_sm && !netdev->owe && !netdev->fils)
|
||||
return;
|
||||
|
||||
if (!l_genl_attr_init(&attr, msg)) {
|
||||
@ -2408,6 +2410,8 @@ static void netdev_authenticate_event(struct l_genl_msg *msg,
|
||||
frame + 26, frame_len - 26);
|
||||
else if (netdev->owe)
|
||||
owe_rx_authenticate(netdev->owe);
|
||||
else if (netdev->fils)
|
||||
fils_rx_authenticate(netdev->fils, frame, frame_len);
|
||||
else
|
||||
goto auth_error;
|
||||
|
||||
@ -2433,7 +2437,8 @@ static void netdev_associate_event(struct l_genl_msg *msg,
|
||||
if (netdev->aborting)
|
||||
return;
|
||||
|
||||
if (!netdev->owe && !netdev->in_ft && !netdev->handshake->mde)
|
||||
if (!netdev->owe && !netdev->in_ft && !netdev->handshake->mde &&
|
||||
!netdev->fils)
|
||||
return;
|
||||
|
||||
if (!l_genl_attr_init(&attr, msg)) {
|
||||
@ -2461,6 +2466,9 @@ static void netdev_associate_event(struct l_genl_msg *msg,
|
||||
if (netdev->owe) {
|
||||
owe_rx_associate(netdev->owe, frame, frame_len);
|
||||
return;
|
||||
} else if (netdev->fils) {
|
||||
fils_rx_associate(netdev->fils, frame, frame_len);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!netdev_ft_process_associate(netdev, frame, frame_len,
|
||||
@ -2638,7 +2646,7 @@ static int netdev_tx_sae_frame(const uint8_t *dest, const uint8_t *body,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void netdev_owe_auth_cb(struct l_genl_msg *msg, void *user_data)
|
||||
static void netdev_auth_cb(struct l_genl_msg *msg, void *user_data)
|
||||
{
|
||||
struct netdev *netdev = user_data;
|
||||
|
||||
@ -2661,7 +2669,7 @@ static void netdev_owe_tx_authenticate(void *user_data)
|
||||
NL80211_AUTHTYPE_OPEN_SYSTEM,
|
||||
netdev->handshake->aa);
|
||||
|
||||
if (!l_genl_family_send(nl80211, msg, netdev_owe_auth_cb,
|
||||
if (!l_genl_family_send(nl80211, msg, netdev_auth_cb,
|
||||
netdev, NULL)) {
|
||||
l_genl_msg_unref(msg);
|
||||
netdev_connect_failed(netdev,
|
||||
@ -2670,7 +2678,7 @@ static void netdev_owe_tx_authenticate(void *user_data)
|
||||
}
|
||||
}
|
||||
|
||||
static void netdev_owe_assoc_cb(struct l_genl_msg *msg, void *user_data)
|
||||
static void netdev_assoc_cb(struct l_genl_msg *msg, void *user_data)
|
||||
{
|
||||
struct netdev *netdev = user_data;
|
||||
|
||||
@ -2692,7 +2700,7 @@ static void netdev_owe_tx_associate(struct iovec *ie_iov, size_t iov_len,
|
||||
|
||||
l_genl_msg_append_attrv(msg, NL80211_ATTR_IE, ie_iov, iov_len);
|
||||
|
||||
if (!l_genl_family_send(nl80211, msg, netdev_owe_assoc_cb,
|
||||
if (!l_genl_family_send(nl80211, msg, netdev_assoc_cb,
|
||||
netdev, NULL)) {
|
||||
l_genl_msg_unref(msg);
|
||||
netdev_connect_failed(netdev, NETDEV_RESULT_ASSOCIATION_FAILED,
|
||||
@ -2727,6 +2735,88 @@ static void netdev_owe_complete(uint16_t status, void *user_data)
|
||||
eapol_start(netdev->sm);
|
||||
}
|
||||
|
||||
static void netdev_fils_tx_authenticate(const uint8_t *body,
|
||||
size_t body_len,
|
||||
void *user_data)
|
||||
{
|
||||
struct netdev *netdev = user_data;
|
||||
struct l_genl_msg *msg;
|
||||
|
||||
msg = netdev_build_cmd_authenticate(netdev, NL80211_AUTHTYPE_FILS_SK,
|
||||
netdev->handshake->aa);
|
||||
|
||||
l_genl_msg_append_attr(msg, NL80211_ATTR_AUTH_DATA, body_len, body);
|
||||
|
||||
if (!l_genl_family_send(nl80211, msg, netdev_auth_cb,
|
||||
netdev, NULL)) {
|
||||
l_genl_msg_unref(msg);
|
||||
netdev_connect_failed(netdev,
|
||||
NETDEV_RESULT_AUTHENTICATION_FAILED,
|
||||
MMPDU_STATUS_CODE_UNSPECIFIED);
|
||||
}
|
||||
}
|
||||
|
||||
static void netdev_fils_tx_associate(struct iovec *iov, size_t iov_len,
|
||||
const uint8_t *kek, size_t kek_len,
|
||||
const uint8_t *nonces, size_t nonces_len,
|
||||
void *user_data)
|
||||
{
|
||||
struct netdev *netdev = user_data;
|
||||
struct l_genl_msg *msg;
|
||||
|
||||
msg = netdev_build_cmd_associate_common(netdev);
|
||||
|
||||
l_genl_msg_append_attrv(msg, NL80211_ATTR_IE, iov, iov_len);
|
||||
|
||||
l_genl_msg_append_attr(msg, NL80211_ATTR_FILS_KEK, kek_len, kek);
|
||||
l_genl_msg_append_attr(msg, NL80211_ATTR_FILS_NONCES, nonces_len, nonces);
|
||||
|
||||
if (!l_genl_family_send(nl80211, msg, netdev_assoc_cb,
|
||||
netdev, NULL)) {
|
||||
l_genl_msg_unref(msg);
|
||||
netdev_connect_failed(netdev, NETDEV_RESULT_ASSOCIATION_FAILED,
|
||||
MMPDU_STATUS_CODE_UNSPECIFIED);
|
||||
}
|
||||
}
|
||||
|
||||
static void netdev_fils_complete(uint16_t status, bool in_auth, bool ap_reject,
|
||||
void *user_data)
|
||||
{
|
||||
struct netdev *netdev = user_data;
|
||||
|
||||
fils_sm_free(netdev->fils);
|
||||
netdev->fils = NULL;
|
||||
|
||||
if (status == 0) {
|
||||
netdev->ignore_connect_event = true;
|
||||
|
||||
/* Register SM for rekeying */
|
||||
netdev->sm = eapol_sm_new(netdev->handshake);
|
||||
eapol_register(netdev->sm);
|
||||
eapol_set_started(netdev->sm);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* There are a few scenarios here:
|
||||
*
|
||||
* 1. AP rejected authentication, this case we are done.
|
||||
* 2. AP accepted either authentication or association where status was
|
||||
* zero, but we failed for some other reason. In these cases we
|
||||
* should set expect_connect_failure which causes a deauth.
|
||||
* 3. AP rejected association. This will be a non zero status code, so
|
||||
* the kernel should know that we have failed the connection.
|
||||
*/
|
||||
|
||||
if (!ap_reject)
|
||||
netdev->expect_connect_failure = true;
|
||||
|
||||
netdev->result = (in_auth) ? NETDEV_RESULT_AUTHENTICATION_FAILED :
|
||||
NETDEV_RESULT_ASSOCIATION_FAILED;
|
||||
netdev->last_code = status;
|
||||
}
|
||||
|
||||
static struct l_genl_msg *netdev_build_cmd_connect(struct netdev *netdev,
|
||||
struct scan_bss *bss,
|
||||
struct handshake_state *hs,
|
||||
@ -2861,6 +2951,8 @@ static int netdev_connect_common(struct netdev *netdev,
|
||||
sae_start(netdev->sae_sm);
|
||||
else if (netdev->owe)
|
||||
owe_start(netdev->owe);
|
||||
else if (netdev->fils)
|
||||
fils_start(netdev->fils);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2892,6 +2984,12 @@ int netdev_connect(struct netdev *netdev, struct scan_bss *bss,
|
||||
netdev_owe_complete,
|
||||
netdev);
|
||||
break;
|
||||
case IE_RSN_AKM_SUITE_FILS_SHA256:
|
||||
case IE_RSN_AKM_SUITE_FILS_SHA384:
|
||||
netdev->fils = fils_sm_new(hs, netdev_fils_tx_authenticate,
|
||||
netdev_fils_tx_associate,
|
||||
netdev_fils_complete, netdev);
|
||||
break;
|
||||
default:
|
||||
cmd_connect = netdev_build_cmd_connect(netdev, bss, hs, NULL);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user