mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-21 22:09:23 +01:00
owe: netdev: refactor to remove OWE as an auth-proto
This commit is contained in:
parent
038b9bff4d
commit
8b6ad5d3b9
545
src/netdev.c
545
src/netdev.c
@ -119,6 +119,7 @@ struct netdev {
|
|||||||
void *user_data;
|
void *user_data;
|
||||||
struct eapol_sm *sm;
|
struct eapol_sm *sm;
|
||||||
struct auth_proto *ap;
|
struct auth_proto *ap;
|
||||||
|
struct owe_sm *owe_sm;
|
||||||
struct handshake_state *handshake;
|
struct handshake_state *handshake;
|
||||||
uint32_t connect_cmd_id;
|
uint32_t connect_cmd_id;
|
||||||
uint32_t disconnect_cmd_id;
|
uint32_t disconnect_cmd_id;
|
||||||
@ -752,6 +753,11 @@ static void netdev_connect_free(struct netdev *netdev)
|
|||||||
netdev->ap = NULL;
|
netdev->ap = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (netdev->owe_sm) {
|
||||||
|
owe_sm_free(netdev->owe_sm);
|
||||||
|
netdev->owe_sm = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
eapol_preauth_cancel(netdev->index);
|
eapol_preauth_cancel(netdev->index);
|
||||||
|
|
||||||
if (netdev->handshake) {
|
if (netdev->handshake) {
|
||||||
@ -2094,6 +2100,228 @@ static void netdev_driver_connected(struct netdev *netdev)
|
|||||||
eapol_register(netdev->sm);
|
eapol_register(netdev->sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int ie_rsn_akm_suite_to_nl80211(enum ie_rsn_akm_suite akm)
|
||||||
|
{
|
||||||
|
switch (akm) {
|
||||||
|
case IE_RSN_AKM_SUITE_8021X:
|
||||||
|
return CRYPTO_AKM_8021X;
|
||||||
|
case IE_RSN_AKM_SUITE_PSK:
|
||||||
|
return CRYPTO_AKM_PSK;
|
||||||
|
case IE_RSN_AKM_SUITE_FT_OVER_8021X:
|
||||||
|
return CRYPTO_AKM_FT_OVER_8021X;
|
||||||
|
case IE_RSN_AKM_SUITE_FT_USING_PSK:
|
||||||
|
return CRYPTO_AKM_FT_USING_PSK;
|
||||||
|
case IE_RSN_AKM_SUITE_8021X_SHA256:
|
||||||
|
return CRYPTO_AKM_8021X_SHA256;
|
||||||
|
case IE_RSN_AKM_SUITE_PSK_SHA256:
|
||||||
|
return CRYPTO_AKM_PSK_SHA256;
|
||||||
|
case IE_RSN_AKM_SUITE_TDLS:
|
||||||
|
return CRYPTO_AKM_TDLS;
|
||||||
|
case IE_RSN_AKM_SUITE_SAE_SHA256:
|
||||||
|
return CRYPTO_AKM_SAE_SHA256;
|
||||||
|
case IE_RSN_AKM_SUITE_FT_OVER_SAE_SHA256:
|
||||||
|
return CRYPTO_AKM_FT_OVER_SAE_SHA256;
|
||||||
|
case IE_RSN_AKM_SUITE_AP_PEER_KEY_SHA256:
|
||||||
|
return CRYPTO_AKM_AP_PEER_KEY_SHA256;
|
||||||
|
case IE_RSN_AKM_SUITE_8021X_SUITE_B_SHA256:
|
||||||
|
return CRYPTO_AKM_8021X_SUITE_B_SHA256;
|
||||||
|
case IE_RSN_AKM_SUITE_8021X_SUITE_B_SHA384:
|
||||||
|
return CRYPTO_AKM_8021X_SUITE_B_SHA384;
|
||||||
|
case IE_RSN_AKM_SUITE_FT_OVER_8021X_SHA384:
|
||||||
|
return CRYPTO_AKM_FT_OVER_8021X_SHA384;
|
||||||
|
case IE_RSN_AKM_SUITE_FILS_SHA256:
|
||||||
|
return CRYPTO_AKM_FILS_SHA256;
|
||||||
|
case IE_RSN_AKM_SUITE_FILS_SHA384:
|
||||||
|
return CRYPTO_AKM_FILS_SHA384;
|
||||||
|
case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256:
|
||||||
|
return CRYPTO_AKM_FT_OVER_FILS_SHA256;
|
||||||
|
case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA384:
|
||||||
|
return CRYPTO_AKM_FT_OVER_FILS_SHA384;
|
||||||
|
case IE_RSN_AKM_SUITE_OWE:
|
||||||
|
return CRYPTO_AKM_OWE;
|
||||||
|
case IE_RSN_AKM_SUITE_OSEN:
|
||||||
|
return CRYPTO_AKM_OSEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct l_genl_msg *netdev_build_cmd_connect(struct netdev *netdev,
|
||||||
|
struct handshake_state *hs,
|
||||||
|
const uint8_t *prev_bssid,
|
||||||
|
const struct iovec *vendor_ies,
|
||||||
|
size_t num_vendor_ies)
|
||||||
|
{
|
||||||
|
struct netdev_handshake_state *nhs =
|
||||||
|
l_container_of(hs, struct netdev_handshake_state, super);
|
||||||
|
uint32_t auth_type = IE_AKM_IS_SAE(hs->akm_suite) ?
|
||||||
|
NL80211_AUTHTYPE_SAE :
|
||||||
|
NL80211_AUTHTYPE_OPEN_SYSTEM;
|
||||||
|
enum mpdu_management_subtype subtype = prev_bssid ?
|
||||||
|
MPDU_MANAGEMENT_SUBTYPE_REASSOCIATION_REQUEST :
|
||||||
|
MPDU_MANAGEMENT_SUBTYPE_ASSOCIATION_REQUEST;
|
||||||
|
struct l_genl_msg *msg;
|
||||||
|
struct iovec iov[64];
|
||||||
|
unsigned int n_iov = L_ARRAY_SIZE(iov);
|
||||||
|
unsigned int c_iov = 0;
|
||||||
|
bool is_rsn = hs->supplicant_ie != NULL;
|
||||||
|
uint8_t owe_dh_ie[5 + L_ECC_SCALAR_MAX_BYTES];
|
||||||
|
size_t dh_ie_len;
|
||||||
|
|
||||||
|
msg = l_genl_msg_new_sized(NL80211_CMD_CONNECT, 512);
|
||||||
|
l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index);
|
||||||
|
l_genl_msg_append_attr(msg, NL80211_ATTR_WIPHY_FREQ,
|
||||||
|
4, &netdev->frequency);
|
||||||
|
l_genl_msg_append_attr(msg, NL80211_ATTR_MAC, ETH_ALEN, hs->aa);
|
||||||
|
l_genl_msg_append_attr(msg, NL80211_ATTR_SSID, hs->ssid_len, hs->ssid);
|
||||||
|
l_genl_msg_append_attr(msg, NL80211_ATTR_AUTH_TYPE, 4, &auth_type);
|
||||||
|
|
||||||
|
switch (nhs->type) {
|
||||||
|
case CONNECTION_TYPE_SOFTMAC:
|
||||||
|
case CONNECTION_TYPE_FULLMAC:
|
||||||
|
break;
|
||||||
|
case CONNECTION_TYPE_SAE_OFFLOAD:
|
||||||
|
l_genl_msg_append_attr(msg, NL80211_ATTR_SAE_PASSWORD,
|
||||||
|
strlen(hs->passphrase), hs->passphrase);
|
||||||
|
break;
|
||||||
|
case CONNECTION_TYPE_PSK_OFFLOAD:
|
||||||
|
l_genl_msg_append_attr(msg, NL80211_ATTR_PMK, 32, hs->pmk);
|
||||||
|
break;
|
||||||
|
case CONNECTION_TYPE_8021X_OFFLOAD:
|
||||||
|
l_genl_msg_append_attr(msg, NL80211_ATTR_WANT_1X_4WAY_HS,
|
||||||
|
0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prev_bssid)
|
||||||
|
l_genl_msg_append_attr(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN,
|
||||||
|
prev_bssid);
|
||||||
|
|
||||||
|
if (netdev->privacy)
|
||||||
|
l_genl_msg_append_attr(msg, NL80211_ATTR_PRIVACY, 0, NULL);
|
||||||
|
|
||||||
|
l_genl_msg_append_attr(msg, NL80211_ATTR_SOCKET_OWNER, 0, NULL);
|
||||||
|
|
||||||
|
if (is_rsn) {
|
||||||
|
uint32_t nl_cipher;
|
||||||
|
uint32_t nl_akm;
|
||||||
|
uint32_t wpa_version;
|
||||||
|
|
||||||
|
if (hs->pairwise_cipher == IE_RSN_CIPHER_SUITE_CCMP)
|
||||||
|
nl_cipher = CRYPTO_CIPHER_CCMP;
|
||||||
|
else
|
||||||
|
nl_cipher = CRYPTO_CIPHER_TKIP;
|
||||||
|
|
||||||
|
l_genl_msg_append_attr(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
|
||||||
|
4, &nl_cipher);
|
||||||
|
|
||||||
|
if (hs->group_cipher == IE_RSN_CIPHER_SUITE_CCMP)
|
||||||
|
nl_cipher = CRYPTO_CIPHER_CCMP;
|
||||||
|
else
|
||||||
|
nl_cipher = CRYPTO_CIPHER_TKIP;
|
||||||
|
|
||||||
|
l_genl_msg_append_attr(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,
|
||||||
|
4, &nl_cipher);
|
||||||
|
|
||||||
|
if (hs->mfp) {
|
||||||
|
uint32_t use_mfp = NL80211_MFP_REQUIRED;
|
||||||
|
l_genl_msg_append_attr(msg, NL80211_ATTR_USE_MFP,
|
||||||
|
4, &use_mfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
nl_akm = ie_rsn_akm_suite_to_nl80211(hs->akm_suite);
|
||||||
|
if (nl_akm)
|
||||||
|
l_genl_msg_append_attr(msg, NL80211_ATTR_AKM_SUITES,
|
||||||
|
4, &nl_akm);
|
||||||
|
|
||||||
|
if (IE_AKM_IS_SAE(hs->akm_suite))
|
||||||
|
wpa_version = NL80211_WPA_VERSION_3;
|
||||||
|
else if (hs->wpa_ie)
|
||||||
|
wpa_version = NL80211_WPA_VERSION_1;
|
||||||
|
else
|
||||||
|
wpa_version = NL80211_WPA_VERSION_2;
|
||||||
|
|
||||||
|
l_genl_msg_append_attr(msg, NL80211_ATTR_WPA_VERSIONS,
|
||||||
|
4, &wpa_version);
|
||||||
|
|
||||||
|
l_genl_msg_append_attr(msg, NL80211_ATTR_CONTROL_PORT, 0, NULL);
|
||||||
|
c_iov = iov_ie_append(iov, n_iov, c_iov, hs->supplicant_ie);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (netdev->owe_sm) {
|
||||||
|
owe_build_dh_ie(netdev->owe_sm, owe_dh_ie, &dh_ie_len);
|
||||||
|
c_iov = iov_ie_append(iov, n_iov, c_iov, owe_dh_ie);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (netdev->pae_over_nl80211)
|
||||||
|
l_genl_msg_append_attr(msg,
|
||||||
|
NL80211_ATTR_CONTROL_PORT_OVER_NL80211,
|
||||||
|
0, NULL);
|
||||||
|
|
||||||
|
c_iov = iov_ie_append(iov, n_iov, c_iov, hs->mde);
|
||||||
|
c_iov = netdev_populate_common_ies(netdev, hs, msg, iov, n_iov, c_iov);
|
||||||
|
|
||||||
|
mpdu_sort_ies(subtype, iov, c_iov);
|
||||||
|
|
||||||
|
if (vendor_ies && !L_WARN_ON(n_iov - c_iov < num_vendor_ies)) {
|
||||||
|
memcpy(iov + c_iov, vendor_ies,
|
||||||
|
sizeof(*vendor_ies) * num_vendor_ies);
|
||||||
|
c_iov += num_vendor_ies;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c_iov)
|
||||||
|
l_genl_msg_append_attrv(msg, NL80211_ATTR_IE, iov, c_iov);
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void netdev_cmd_connect_cb(struct l_genl_msg *msg, void *user_data)
|
||||||
|
{
|
||||||
|
struct netdev *netdev = user_data;
|
||||||
|
|
||||||
|
netdev->connect_cmd_id = 0;
|
||||||
|
|
||||||
|
if (l_genl_msg_get_error(msg) >= 0) {
|
||||||
|
/*
|
||||||
|
* connected should be false if the connect event hasn't come
|
||||||
|
* in yet. i.e. the CMD_CONNECT ack arrived first (typical).
|
||||||
|
* Mark the connection as 'connected'
|
||||||
|
*/
|
||||||
|
if (!netdev->connected)
|
||||||
|
netdev_driver_connected(netdev);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
netdev_connect_failed(netdev, NETDEV_RESULT_ASSOCIATION_FAILED,
|
||||||
|
MMPDU_STATUS_CODE_UNSPECIFIED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool netdev_retry_owe(struct netdev *netdev)
|
||||||
|
{
|
||||||
|
struct iovec iov;
|
||||||
|
|
||||||
|
if (!owe_next_group(netdev->owe_sm))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
iov.iov_base = netdev->handshake->vendor_ies;
|
||||||
|
iov.iov_len = netdev->handshake->vendor_ies_len;
|
||||||
|
|
||||||
|
netdev->connect_cmd = netdev_build_cmd_connect(netdev,
|
||||||
|
netdev->handshake, NULL, &iov, 1);
|
||||||
|
|
||||||
|
netdev->connect_cmd_id = l_genl_family_send(nl80211,
|
||||||
|
netdev->connect_cmd,
|
||||||
|
netdev_cmd_connect_cb, netdev,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (!netdev->connect_cmd_id)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
netdev->connect_cmd = NULL;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void netdev_connect_event(struct l_genl_msg *msg, struct netdev *netdev)
|
static void netdev_connect_event(struct l_genl_msg *msg, struct netdev *netdev)
|
||||||
{
|
{
|
||||||
struct l_genl_attr attr;
|
struct l_genl_attr attr;
|
||||||
@ -2162,6 +2390,14 @@ static void netdev_connect_event(struct l_genl_msg *msg, struct netdev *netdev)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (netdev->owe_sm && status_code && *status_code ==
|
||||||
|
MMPDU_STATUS_CODE_UNSUPP_FINITE_CYCLIC_GROUP) {
|
||||||
|
if (!netdev_retry_owe(netdev))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* AP Rejected the authenticate / associate */
|
/* AP Rejected the authenticate / associate */
|
||||||
if (!status_code || *status_code != 0)
|
if (!status_code || *status_code != 0)
|
||||||
goto error;
|
goto error;
|
||||||
@ -2175,8 +2411,12 @@ process_resp_ies:
|
|||||||
if (resp_ies) {
|
if (resp_ies) {
|
||||||
const uint8_t *fte = NULL;
|
const uint8_t *fte = NULL;
|
||||||
const uint8_t *qos_set = NULL;
|
const uint8_t *qos_set = NULL;
|
||||||
|
const uint8_t *owe_dh = NULL;
|
||||||
|
size_t owe_dh_len = 0;
|
||||||
size_t qos_len = 0;
|
size_t qos_len = 0;
|
||||||
struct ie_ft_info ft_info;
|
struct ie_ft_info ft_info;
|
||||||
|
struct ie_rsn_info info;
|
||||||
|
bool owe_akm_found = false;
|
||||||
|
|
||||||
ie_tlv_iter_init(&iter, resp_ies, resp_ies_len);
|
ie_tlv_iter_init(&iter, resp_ies, resp_ies_len);
|
||||||
|
|
||||||
@ -2203,9 +2443,55 @@ process_resp_ies:
|
|||||||
data - 3,
|
data - 3,
|
||||||
ie_tlv_iter_get_length(&iter) + 3);
|
ie_tlv_iter_get_length(&iter) + 3);
|
||||||
break;
|
break;
|
||||||
|
case IE_TYPE_OWE_DH_PARAM:
|
||||||
|
if (!netdev->owe_sm)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
owe_dh = data;
|
||||||
|
owe_dh_len = len;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IE_TYPE_RSN:
|
||||||
|
if (!netdev->owe_sm)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ie_parse_rsne(&iter, &info) < 0) {
|
||||||
|
l_error("could not parse RSN IE");
|
||||||
|
goto deauth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RFC 8110 Section 4.2
|
||||||
|
* An AP agreeing to do OWE MUST include the
|
||||||
|
* OWE AKM in the RSN element portion of the
|
||||||
|
* 802.11 association response.
|
||||||
|
*/
|
||||||
|
if (info.akm_suites != IE_RSN_AKM_SUITE_OWE) {
|
||||||
|
l_error("OWE AKM not included");
|
||||||
|
goto deauth;
|
||||||
|
}
|
||||||
|
|
||||||
|
owe_akm_found = true;
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (netdev->owe_sm) {
|
||||||
|
if (!owe_dh || !owe_akm_found) {
|
||||||
|
l_error("OWE DH element/RSN not found");
|
||||||
|
goto deauth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (L_WARN_ON(owe_process_dh_ie(netdev->owe_sm, owe_dh,
|
||||||
|
owe_dh_len) != 0))
|
||||||
|
goto deauth;
|
||||||
|
|
||||||
|
owe_sm_free(netdev->owe_sm);
|
||||||
|
netdev->owe_sm = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* FILS handles its own FT key derivation */
|
/* FILS handles its own FT key derivation */
|
||||||
if (fte && !(netdev->handshake->akm_suite &
|
if (fte && !(netdev->handshake->akm_suite &
|
||||||
(IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256 |
|
(IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256 |
|
||||||
@ -2271,52 +2557,6 @@ deauth:
|
|||||||
netdev, NULL);
|
netdev, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int ie_rsn_akm_suite_to_nl80211(enum ie_rsn_akm_suite akm)
|
|
||||||
{
|
|
||||||
switch (akm) {
|
|
||||||
case IE_RSN_AKM_SUITE_8021X:
|
|
||||||
return CRYPTO_AKM_8021X;
|
|
||||||
case IE_RSN_AKM_SUITE_PSK:
|
|
||||||
return CRYPTO_AKM_PSK;
|
|
||||||
case IE_RSN_AKM_SUITE_FT_OVER_8021X:
|
|
||||||
return CRYPTO_AKM_FT_OVER_8021X;
|
|
||||||
case IE_RSN_AKM_SUITE_FT_USING_PSK:
|
|
||||||
return CRYPTO_AKM_FT_USING_PSK;
|
|
||||||
case IE_RSN_AKM_SUITE_8021X_SHA256:
|
|
||||||
return CRYPTO_AKM_8021X_SHA256;
|
|
||||||
case IE_RSN_AKM_SUITE_PSK_SHA256:
|
|
||||||
return CRYPTO_AKM_PSK_SHA256;
|
|
||||||
case IE_RSN_AKM_SUITE_TDLS:
|
|
||||||
return CRYPTO_AKM_TDLS;
|
|
||||||
case IE_RSN_AKM_SUITE_SAE_SHA256:
|
|
||||||
return CRYPTO_AKM_SAE_SHA256;
|
|
||||||
case IE_RSN_AKM_SUITE_FT_OVER_SAE_SHA256:
|
|
||||||
return CRYPTO_AKM_FT_OVER_SAE_SHA256;
|
|
||||||
case IE_RSN_AKM_SUITE_AP_PEER_KEY_SHA256:
|
|
||||||
return CRYPTO_AKM_AP_PEER_KEY_SHA256;
|
|
||||||
case IE_RSN_AKM_SUITE_8021X_SUITE_B_SHA256:
|
|
||||||
return CRYPTO_AKM_8021X_SUITE_B_SHA256;
|
|
||||||
case IE_RSN_AKM_SUITE_8021X_SUITE_B_SHA384:
|
|
||||||
return CRYPTO_AKM_8021X_SUITE_B_SHA384;
|
|
||||||
case IE_RSN_AKM_SUITE_FT_OVER_8021X_SHA384:
|
|
||||||
return CRYPTO_AKM_FT_OVER_8021X_SHA384;
|
|
||||||
case IE_RSN_AKM_SUITE_FILS_SHA256:
|
|
||||||
return CRYPTO_AKM_FILS_SHA256;
|
|
||||||
case IE_RSN_AKM_SUITE_FILS_SHA384:
|
|
||||||
return CRYPTO_AKM_FILS_SHA384;
|
|
||||||
case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256:
|
|
||||||
return CRYPTO_AKM_FT_OVER_FILS_SHA256;
|
|
||||||
case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA384:
|
|
||||||
return CRYPTO_AKM_FT_OVER_FILS_SHA384;
|
|
||||||
case IE_RSN_AKM_SUITE_OWE:
|
|
||||||
return CRYPTO_AKM_OWE;
|
|
||||||
case IE_RSN_AKM_SUITE_OSEN:
|
|
||||||
return CRYPTO_AKM_OSEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct l_genl_msg *netdev_build_cmd_associate_common(
|
static struct l_genl_msg *netdev_build_cmd_associate_common(
|
||||||
struct netdev *netdev)
|
struct netdev *netdev)
|
||||||
{
|
{
|
||||||
@ -2602,28 +2842,6 @@ assoc_failed:
|
|||||||
netdev->expect_connect_failure = true;
|
netdev->expect_connect_failure = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void netdev_cmd_connect_cb(struct l_genl_msg *msg, void *user_data)
|
|
||||||
{
|
|
||||||
struct netdev *netdev = user_data;
|
|
||||||
|
|
||||||
netdev->connect_cmd_id = 0;
|
|
||||||
|
|
||||||
if (l_genl_msg_get_error(msg) >= 0) {
|
|
||||||
/*
|
|
||||||
* connected should be false if the connect event hasn't come
|
|
||||||
* in yet. i.e. the CMD_CONNECT ack arrived first (typical).
|
|
||||||
* Mark the connection as 'connected'
|
|
||||||
*/
|
|
||||||
if (!netdev->connected)
|
|
||||||
netdev_driver_connected(netdev);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
netdev_connect_failed(netdev, NETDEV_RESULT_ASSOCIATION_FAILED,
|
|
||||||
MMPDU_STATUS_CODE_UNSPECIFIED);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct l_genl_msg *netdev_build_cmd_authenticate(struct netdev *netdev,
|
static struct l_genl_msg *netdev_build_cmd_authenticate(struct netdev *netdev,
|
||||||
uint32_t auth_type)
|
uint32_t auth_type)
|
||||||
{
|
{
|
||||||
@ -2777,64 +2995,6 @@ static void netdev_sae_tx_associate(void *user_data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void netdev_owe_tx_authenticate(void *user_data)
|
|
||||||
{
|
|
||||||
struct netdev *netdev = user_data;
|
|
||||||
struct l_genl_msg *msg;
|
|
||||||
|
|
||||||
msg = netdev_build_cmd_authenticate(netdev,
|
|
||||||
NL80211_AUTHTYPE_OPEN_SYSTEM);
|
|
||||||
|
|
||||||
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);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
netdev->auth_cmd = l_genl_msg_ref(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netdev_owe_tx_associate(struct iovec *owe_iov, size_t n_owe_iov,
|
|
||||||
void *user_data)
|
|
||||||
{
|
|
||||||
struct netdev *netdev = user_data;
|
|
||||||
struct handshake_state *hs = netdev->handshake;
|
|
||||||
struct l_genl_msg *msg;
|
|
||||||
struct iovec iov[64];
|
|
||||||
unsigned int n_iov = L_ARRAY_SIZE(iov);
|
|
||||||
unsigned int c_iov = 0;
|
|
||||||
enum mpdu_management_subtype subtype =
|
|
||||||
MPDU_MANAGEMENT_SUBTYPE_ASSOCIATION_REQUEST;
|
|
||||||
|
|
||||||
msg = netdev_build_cmd_associate_common(netdev);
|
|
||||||
|
|
||||||
c_iov = netdev_populate_common_ies(netdev, hs, msg, iov, n_iov, c_iov);
|
|
||||||
|
|
||||||
if (!L_WARN_ON(n_iov - c_iov < n_owe_iov)) {
|
|
||||||
memcpy(iov + c_iov, owe_iov, sizeof(*owe_iov) * n_owe_iov);
|
|
||||||
c_iov += n_owe_iov;
|
|
||||||
}
|
|
||||||
|
|
||||||
mpdu_sort_ies(subtype, iov, c_iov);
|
|
||||||
|
|
||||||
l_genl_msg_append_attrv(msg, NL80211_ATTR_IE, iov, c_iov);
|
|
||||||
|
|
||||||
/* If doing a non-FT Reassociation */
|
|
||||||
if (netdev->in_reassoc)
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_PREV_BSSID, 6,
|
|
||||||
netdev->ap->prev_bssid);
|
|
||||||
|
|
||||||
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_tx_authenticate(const uint8_t *body,
|
static void netdev_fils_tx_authenticate(const uint8_t *body,
|
||||||
size_t body_len,
|
size_t body_len,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
@ -2902,127 +3062,6 @@ static void netdev_fils_tx_associate(struct iovec *fils_iov, size_t n_fils_iov,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct l_genl_msg *netdev_build_cmd_connect(struct netdev *netdev,
|
|
||||||
struct handshake_state *hs,
|
|
||||||
const uint8_t *prev_bssid,
|
|
||||||
const struct iovec *vendor_ies,
|
|
||||||
size_t num_vendor_ies)
|
|
||||||
{
|
|
||||||
struct netdev_handshake_state *nhs =
|
|
||||||
l_container_of(hs, struct netdev_handshake_state, super);
|
|
||||||
uint32_t auth_type = IE_AKM_IS_SAE(hs->akm_suite) ?
|
|
||||||
NL80211_AUTHTYPE_SAE :
|
|
||||||
NL80211_AUTHTYPE_OPEN_SYSTEM;
|
|
||||||
enum mpdu_management_subtype subtype = prev_bssid ?
|
|
||||||
MPDU_MANAGEMENT_SUBTYPE_REASSOCIATION_REQUEST :
|
|
||||||
MPDU_MANAGEMENT_SUBTYPE_ASSOCIATION_REQUEST;
|
|
||||||
struct l_genl_msg *msg;
|
|
||||||
struct iovec iov[64];
|
|
||||||
unsigned int n_iov = L_ARRAY_SIZE(iov);
|
|
||||||
unsigned int c_iov = 0;
|
|
||||||
bool is_rsn = hs->supplicant_ie != NULL;
|
|
||||||
|
|
||||||
msg = l_genl_msg_new_sized(NL80211_CMD_CONNECT, 512);
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_IFINDEX, 4, &netdev->index);
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_WIPHY_FREQ,
|
|
||||||
4, &netdev->frequency);
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_MAC, ETH_ALEN, hs->aa);
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_SSID, hs->ssid_len, hs->ssid);
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_AUTH_TYPE, 4, &auth_type);
|
|
||||||
|
|
||||||
switch (nhs->type) {
|
|
||||||
case CONNECTION_TYPE_SOFTMAC:
|
|
||||||
case CONNECTION_TYPE_FULLMAC:
|
|
||||||
break;
|
|
||||||
case CONNECTION_TYPE_SAE_OFFLOAD:
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_SAE_PASSWORD,
|
|
||||||
strlen(hs->passphrase), hs->passphrase);
|
|
||||||
break;
|
|
||||||
case CONNECTION_TYPE_PSK_OFFLOAD:
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_PMK, 32, hs->pmk);
|
|
||||||
break;
|
|
||||||
case CONNECTION_TYPE_8021X_OFFLOAD:
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_WANT_1X_4WAY_HS,
|
|
||||||
0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prev_bssid)
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN,
|
|
||||||
prev_bssid);
|
|
||||||
|
|
||||||
if (netdev->privacy)
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_PRIVACY, 0, NULL);
|
|
||||||
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_SOCKET_OWNER, 0, NULL);
|
|
||||||
|
|
||||||
if (is_rsn) {
|
|
||||||
uint32_t nl_cipher;
|
|
||||||
uint32_t nl_akm;
|
|
||||||
uint32_t wpa_version;
|
|
||||||
|
|
||||||
if (hs->pairwise_cipher == IE_RSN_CIPHER_SUITE_CCMP)
|
|
||||||
nl_cipher = CRYPTO_CIPHER_CCMP;
|
|
||||||
else
|
|
||||||
nl_cipher = CRYPTO_CIPHER_TKIP;
|
|
||||||
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
|
|
||||||
4, &nl_cipher);
|
|
||||||
|
|
||||||
if (hs->group_cipher == IE_RSN_CIPHER_SUITE_CCMP)
|
|
||||||
nl_cipher = CRYPTO_CIPHER_CCMP;
|
|
||||||
else
|
|
||||||
nl_cipher = CRYPTO_CIPHER_TKIP;
|
|
||||||
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,
|
|
||||||
4, &nl_cipher);
|
|
||||||
|
|
||||||
if (hs->mfp) {
|
|
||||||
uint32_t use_mfp = NL80211_MFP_REQUIRED;
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_USE_MFP,
|
|
||||||
4, &use_mfp);
|
|
||||||
}
|
|
||||||
|
|
||||||
nl_akm = ie_rsn_akm_suite_to_nl80211(hs->akm_suite);
|
|
||||||
if (nl_akm)
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_AKM_SUITES,
|
|
||||||
4, &nl_akm);
|
|
||||||
|
|
||||||
if (IE_AKM_IS_SAE(hs->akm_suite))
|
|
||||||
wpa_version = NL80211_WPA_VERSION_3;
|
|
||||||
else if (hs->wpa_ie)
|
|
||||||
wpa_version = NL80211_WPA_VERSION_1;
|
|
||||||
else
|
|
||||||
wpa_version = NL80211_WPA_VERSION_2;
|
|
||||||
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_WPA_VERSIONS,
|
|
||||||
4, &wpa_version);
|
|
||||||
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_CONTROL_PORT, 0, NULL);
|
|
||||||
c_iov = iov_ie_append(iov, n_iov, c_iov, hs->supplicant_ie);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (netdev->pae_over_nl80211)
|
|
||||||
l_genl_msg_append_attr(msg,
|
|
||||||
NL80211_ATTR_CONTROL_PORT_OVER_NL80211,
|
|
||||||
0, NULL);
|
|
||||||
|
|
||||||
c_iov = iov_ie_append(iov, n_iov, c_iov, hs->mde);
|
|
||||||
c_iov = netdev_populate_common_ies(netdev, hs, msg, iov, n_iov, c_iov);
|
|
||||||
|
|
||||||
mpdu_sort_ies(subtype, iov, c_iov);
|
|
||||||
|
|
||||||
if (vendor_ies && !L_WARN_ON(n_iov - c_iov < num_vendor_ies)) {
|
|
||||||
memcpy(iov + c_iov, vendor_ies,
|
|
||||||
sizeof(*vendor_ies) * num_vendor_ies);
|
|
||||||
c_iov += num_vendor_ies;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c_iov)
|
|
||||||
l_genl_msg_append_attrv(msg, NL80211_ATTR_IE, iov, c_iov);
|
|
||||||
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rtnl_data {
|
struct rtnl_data {
|
||||||
struct netdev *netdev;
|
struct netdev *netdev;
|
||||||
uint8_t addr[ETH_ALEN];
|
uint8_t addr[ETH_ALEN];
|
||||||
@ -3397,6 +3436,8 @@ static int netdev_handshake_state_setup_connection_type(
|
|||||||
NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK))
|
NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK))
|
||||||
goto psk_offload;
|
goto psk_offload;
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
|
case IE_RSN_AKM_SUITE_OWE:
|
||||||
if (softmac)
|
if (softmac)
|
||||||
goto softmac;
|
goto softmac;
|
||||||
|
|
||||||
@ -3425,12 +3466,11 @@ static int netdev_handshake_state_setup_connection_type(
|
|||||||
goto softmac;
|
goto softmac;
|
||||||
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
case IE_RSN_AKM_SUITE_OWE:
|
|
||||||
case IE_RSN_AKM_SUITE_FILS_SHA256:
|
case IE_RSN_AKM_SUITE_FILS_SHA256:
|
||||||
case IE_RSN_AKM_SUITE_FILS_SHA384:
|
case IE_RSN_AKM_SUITE_FILS_SHA384:
|
||||||
case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256:
|
case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256:
|
||||||
case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA384:
|
case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA384:
|
||||||
/* FILS and OWE have no offload in any upstream driver */
|
/* FILS has no offload in any upstream driver */
|
||||||
if (softmac)
|
if (softmac)
|
||||||
goto softmac;
|
goto softmac;
|
||||||
|
|
||||||
@ -3509,10 +3549,9 @@ static void netdev_connect_common(struct netdev *netdev,
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case IE_RSN_AKM_SUITE_OWE:
|
case IE_RSN_AKM_SUITE_OWE:
|
||||||
netdev->ap = owe_sm_new(hs, netdev_owe_tx_authenticate,
|
netdev->owe_sm = owe_sm_new(hs);
|
||||||
netdev_owe_tx_associate,
|
|
||||||
netdev);
|
goto build_cmd_connect;
|
||||||
break;
|
|
||||||
case IE_RSN_AKM_SUITE_FILS_SHA256:
|
case IE_RSN_AKM_SUITE_FILS_SHA256:
|
||||||
case IE_RSN_AKM_SUITE_FILS_SHA384:
|
case IE_RSN_AKM_SUITE_FILS_SHA384:
|
||||||
case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256:
|
case IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256:
|
||||||
|
148
src/owe.c
148
src/owe.c
@ -34,7 +34,6 @@
|
|||||||
#include "src/auth-proto.h"
|
#include "src/auth-proto.h"
|
||||||
|
|
||||||
struct owe_sm {
|
struct owe_sm {
|
||||||
struct auth_proto ap;
|
|
||||||
struct handshake_state *hs;
|
struct handshake_state *hs;
|
||||||
const struct l_ecc_curve *curve;
|
const struct l_ecc_curve *curve;
|
||||||
struct l_ecc_scalar *private;
|
struct l_ecc_scalar *private;
|
||||||
@ -42,10 +41,6 @@ struct owe_sm {
|
|||||||
uint8_t retry;
|
uint8_t retry;
|
||||||
uint16_t group;
|
uint16_t group;
|
||||||
const unsigned int *ecc_groups;
|
const unsigned int *ecc_groups;
|
||||||
|
|
||||||
owe_tx_authenticate_func_t auth_tx;
|
|
||||||
owe_tx_associate_func_t assoc_tx;
|
|
||||||
void *user_data;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool owe_reset(struct owe_sm *owe)
|
static bool owe_reset(struct owe_sm *owe)
|
||||||
@ -72,62 +67,28 @@ static bool owe_reset(struct owe_sm *owe)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void owe_free(struct auth_proto *ap)
|
void owe_sm_free(struct owe_sm *owe)
|
||||||
{
|
{
|
||||||
struct owe_sm *owe = l_container_of(ap, struct owe_sm, ap);
|
|
||||||
|
|
||||||
l_ecc_scalar_free(owe->private);
|
l_ecc_scalar_free(owe->private);
|
||||||
l_ecc_point_free(owe->public_key);
|
l_ecc_point_free(owe->public_key);
|
||||||
|
|
||||||
l_free(owe);
|
l_free(owe);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool owe_start(struct auth_proto *ap)
|
void owe_build_dh_ie(struct owe_sm *owe, uint8_t *buf, size_t *len_out)
|
||||||
{
|
{
|
||||||
struct owe_sm *owe = l_container_of(ap, struct owe_sm, ap);
|
|
||||||
|
|
||||||
owe->auth_tx(owe->user_data);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int owe_rx_authenticate(struct auth_proto *ap, const uint8_t *frame,
|
|
||||||
size_t frame_len)
|
|
||||||
{
|
|
||||||
struct owe_sm *owe = l_container_of(ap, struct owe_sm, ap);
|
|
||||||
|
|
||||||
uint8_t buf[5 + L_ECC_SCALAR_MAX_BYTES];
|
|
||||||
struct iovec iov[3];
|
|
||||||
int iov_elems = 0;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RFC 8110 Section 4.3
|
* A client wishing to do OWE ... MUST include a Diffie-Hellman
|
||||||
* A client wishing to do OWE MUST indicate the OWE AKM in the RSN
|
* Parameter element to its 802.11 association request.
|
||||||
* element portion of the 802.11 association request ...
|
|
||||||
*/
|
|
||||||
iov[iov_elems].iov_base = owe->hs->supplicant_ie;
|
|
||||||
iov[iov_elems].iov_len = owe->hs->supplicant_ie[1] + 2;
|
|
||||||
iov_elems++;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ... and MUST include a Diffie-Hellman Parameter element to its
|
|
||||||
* 802.11 association request.
|
|
||||||
*/
|
*/
|
||||||
buf[0] = IE_TYPE_EXTENSION;
|
buf[0] = IE_TYPE_EXTENSION;
|
||||||
buf[2] = IE_TYPE_OWE_DH_PARAM - 256;
|
buf[2] = IE_TYPE_OWE_DH_PARAM - 256;
|
||||||
l_put_le16(owe->group, buf + 3); /* group */
|
l_put_le16(owe->group, buf + 3); /* group */
|
||||||
len = l_ecc_point_get_x(owe->public_key, buf + 5,
|
*len_out = l_ecc_point_get_x(owe->public_key, buf + 5,
|
||||||
L_ECC_SCALAR_MAX_BYTES);
|
L_ECC_SCALAR_MAX_BYTES);
|
||||||
buf[1] = 3 + len; /* length */
|
buf[1] = 3 + *len_out; /* length */
|
||||||
|
|
||||||
iov[iov_elems].iov_base = (void *) buf;
|
*len_out += 5;
|
||||||
iov[iov_elems].iov_len = buf[1] + 2;
|
|
||||||
iov_elems++;
|
|
||||||
|
|
||||||
owe->assoc_tx(iov, iov_elems, owe->user_data);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -220,7 +181,7 @@ failed:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool owe_retry(struct owe_sm *owe)
|
bool owe_next_group(struct owe_sm *owe)
|
||||||
{
|
{
|
||||||
/* retry with another group, if possible */
|
/* retry with another group, if possible */
|
||||||
owe->retry++;
|
owe->retry++;
|
||||||
@ -228,88 +189,23 @@ static bool owe_retry(struct owe_sm *owe)
|
|||||||
if (!owe_reset(owe))
|
if (!owe_reset(owe))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
l_debug("OWE retrying with group %u", owe->group);
|
|
||||||
|
|
||||||
owe_rx_authenticate(&owe->ap, NULL, 0);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int owe_rx_associate(struct auth_proto *ap, const uint8_t *frame,
|
int owe_process_dh_ie(struct owe_sm *owe, const uint8_t *dh, size_t len)
|
||||||
size_t len)
|
|
||||||
{
|
{
|
||||||
struct owe_sm *owe = l_container_of(ap, struct owe_sm, ap);
|
if (!dh || len < 34) {
|
||||||
|
|
||||||
const struct mmpdu_header *mpdu = (const struct mmpdu_header *) frame;
|
|
||||||
const struct mmpdu_association_response *body = mmpdu_body(mpdu);
|
|
||||||
struct ie_tlv_iter iter;
|
|
||||||
size_t owe_dh_len = 0;
|
|
||||||
const uint8_t *owe_dh = NULL;
|
|
||||||
struct ie_rsn_info info;
|
|
||||||
bool akm_found = false;
|
|
||||||
const void *data;
|
|
||||||
|
|
||||||
if (L_LE16_TO_CPU(body->status_code) ==
|
|
||||||
MMPDU_STATUS_CODE_UNSUPP_FINITE_CYCLIC_GROUP) {
|
|
||||||
if (!owe_retry(owe))
|
|
||||||
goto owe_bad_status;
|
|
||||||
|
|
||||||
return -EAGAIN;
|
|
||||||
} else if (body->status_code)
|
|
||||||
goto owe_bad_status;
|
|
||||||
|
|
||||||
ie_tlv_iter_init(&iter, body->ies, (const uint8_t *) mpdu + len -
|
|
||||||
body->ies);
|
|
||||||
|
|
||||||
while (ie_tlv_iter_next(&iter)) {
|
|
||||||
uint16_t tag = ie_tlv_iter_get_tag(&iter);
|
|
||||||
|
|
||||||
data = ie_tlv_iter_get_data(&iter);
|
|
||||||
len = ie_tlv_iter_get_length(&iter);
|
|
||||||
|
|
||||||
switch (tag) {
|
|
||||||
case IE_TYPE_OWE_DH_PARAM:
|
|
||||||
owe_dh = data;
|
|
||||||
owe_dh_len = len;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case IE_TYPE_RSN:
|
|
||||||
if (ie_parse_rsne(&iter, &info) < 0) {
|
|
||||||
l_error("could not parse RSN IE");
|
|
||||||
goto invalid_ies;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* RFC 8110 Section 4.2
|
|
||||||
* An AP agreeing to do OWE MUST include the OWE AKM in
|
|
||||||
* the RSN element portion of the 802.11 association
|
|
||||||
* response.
|
|
||||||
*/
|
|
||||||
if (info.akm_suites != IE_RSN_AKM_SUITE_OWE) {
|
|
||||||
l_error("OWE AKM not included");
|
|
||||||
goto invalid_ies;
|
|
||||||
}
|
|
||||||
|
|
||||||
akm_found = true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!owe_dh || owe_dh_len < 34 || !akm_found) {
|
|
||||||
l_error("associate response did not include proper OWE IE's");
|
l_error("associate response did not include proper OWE IE's");
|
||||||
goto invalid_ies;
|
goto invalid_ies;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l_get_le16(owe_dh) != owe->group) {
|
if (l_get_le16(dh) != owe->group) {
|
||||||
l_error("associate response contained unsupported group %u",
|
l_error("associate response contained unsupported group %u",
|
||||||
l_get_le16(owe_dh));
|
l_get_le16(dh));
|
||||||
return -EBADMSG;
|
return -EBADMSG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!owe_compute_keys(owe, owe_dh + 2, owe_dh_len - 2)) {
|
if (!owe_compute_keys(owe, dh + 2, len - 2)) {
|
||||||
l_error("could not compute OWE keys");
|
l_error("could not compute OWE keys");
|
||||||
return -EBADMSG;
|
return -EBADMSG;
|
||||||
}
|
}
|
||||||
@ -318,33 +214,19 @@ static int owe_rx_associate(struct auth_proto *ap, const uint8_t *frame,
|
|||||||
|
|
||||||
invalid_ies:
|
invalid_ies:
|
||||||
return MMPDU_STATUS_CODE_INVALID_ELEMENT;
|
return MMPDU_STATUS_CODE_INVALID_ELEMENT;
|
||||||
|
|
||||||
owe_bad_status:
|
|
||||||
return L_LE16_TO_CPU(body->status_code);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct auth_proto *owe_sm_new(struct handshake_state *hs,
|
struct owe_sm *owe_sm_new(struct handshake_state *hs)
|
||||||
owe_tx_authenticate_func_t auth,
|
|
||||||
owe_tx_associate_func_t assoc,
|
|
||||||
void *user_data)
|
|
||||||
{
|
{
|
||||||
struct owe_sm *owe = l_new(struct owe_sm, 1);
|
struct owe_sm *owe = l_new(struct owe_sm, 1);
|
||||||
|
|
||||||
owe->hs = hs;
|
owe->hs = hs;
|
||||||
owe->auth_tx = auth;
|
|
||||||
owe->assoc_tx = assoc;
|
|
||||||
owe->user_data = user_data;
|
|
||||||
owe->ecc_groups = l_ecc_supported_ike_groups();
|
owe->ecc_groups = l_ecc_supported_ike_groups();
|
||||||
|
|
||||||
owe->ap.start = owe_start;
|
|
||||||
owe->ap.free = owe_free;
|
|
||||||
owe->ap.rx_authenticate = owe_rx_authenticate;
|
|
||||||
owe->ap.rx_associate = owe_rx_associate;
|
|
||||||
|
|
||||||
if (!owe_reset(owe)) {
|
if (!owe_reset(owe)) {
|
||||||
l_free(owe);
|
l_free(owe);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return &owe->ap;
|
return owe;
|
||||||
}
|
}
|
||||||
|
12
src/owe.h
12
src/owe.h
@ -23,11 +23,9 @@
|
|||||||
struct owe_sm;
|
struct owe_sm;
|
||||||
struct handshake_state;
|
struct handshake_state;
|
||||||
|
|
||||||
typedef void (*owe_tx_authenticate_func_t)(void *user_data);
|
struct owe_sm *owe_sm_new(struct handshake_state *hs);
|
||||||
typedef void (*owe_tx_associate_func_t)(struct iovec *ie_iov, size_t iov_len,
|
void owe_sm_free(struct owe_sm *sm);
|
||||||
void *user_data);
|
|
||||||
|
|
||||||
struct auth_proto *owe_sm_new(struct handshake_state *hs,
|
void owe_build_dh_ie(struct owe_sm *sm, uint8_t *buf, size_t *len_out);
|
||||||
owe_tx_authenticate_func_t auth,
|
int owe_process_dh_ie(struct owe_sm *sm, const uint8_t *dh, size_t len);
|
||||||
owe_tx_associate_func_t assoc,
|
bool owe_next_group(struct owe_sm *sm);
|
||||||
void *user_data);
|
|
||||||
|
Loading…
Reference in New Issue
Block a user