RSNE/RSNXE overriding for AP
Allow hostapd to be configured to advertised two separate sets of RSNE/RSNXE parameters so that RSNE/RSNXE can use a reduced set of capabilities (e.g., WPA2-Personal only) for supporting deployed STAs that have issues with transition modes while the new override elements can use a newer security option (e.g., WPA3-Personal only) for STAs that support the new mechanism. Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
parent
b8a2d11ae0
commit
157b016383
12 changed files with 643 additions and 78 deletions
|
@ -3156,6 +3156,16 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
||||||
bss->wpa_key_mgmt = hostapd_config_parse_key_mgmt(line, pos);
|
bss->wpa_key_mgmt = hostapd_config_parse_key_mgmt(line, pos);
|
||||||
if (bss->wpa_key_mgmt == -1)
|
if (bss->wpa_key_mgmt == -1)
|
||||||
return 1;
|
return 1;
|
||||||
|
} else if (os_strcmp(buf, "rsn_override_key_mgmt") == 0) {
|
||||||
|
bss->rsn_override_key_mgmt =
|
||||||
|
hostapd_config_parse_key_mgmt(line, pos);
|
||||||
|
if (bss->rsn_override_key_mgmt == -1)
|
||||||
|
return 1;
|
||||||
|
} else if (os_strcmp(buf, "rsn_override_key_mgmt_2") == 0) {
|
||||||
|
bss->rsn_override_key_mgmt_2 =
|
||||||
|
hostapd_config_parse_key_mgmt(line, pos);
|
||||||
|
if (bss->rsn_override_key_mgmt_2 == -1)
|
||||||
|
return 1;
|
||||||
} else if (os_strcmp(buf, "wpa_psk_radius") == 0) {
|
} else if (os_strcmp(buf, "wpa_psk_radius") == 0) {
|
||||||
bss->wpa_psk_radius = atoi(pos);
|
bss->wpa_psk_radius = atoi(pos);
|
||||||
if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
|
if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
|
||||||
|
@ -3187,6 +3197,32 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
||||||
line, pos);
|
line, pos);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
} else if (os_strcmp(buf, "rsn_override_pairwise") == 0) {
|
||||||
|
bss->rsn_override_pairwise =
|
||||||
|
hostapd_config_parse_cipher(line, pos);
|
||||||
|
if (bss->rsn_override_pairwise == -1 ||
|
||||||
|
bss->rsn_override_pairwise == 0)
|
||||||
|
return 1;
|
||||||
|
if (bss->rsn_override_pairwise &
|
||||||
|
(WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"Line %d: unsupported pairwise cipher suite '%s'",
|
||||||
|
line, pos);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else if (os_strcmp(buf, "rsn_override_pairwise_2") == 0) {
|
||||||
|
bss->rsn_override_pairwise_2 =
|
||||||
|
hostapd_config_parse_cipher(line, pos);
|
||||||
|
if (bss->rsn_override_pairwise_2 == -1 ||
|
||||||
|
bss->rsn_override_pairwise_2 == 0)
|
||||||
|
return 1;
|
||||||
|
if (bss->rsn_override_pairwise_2 &
|
||||||
|
(WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"Line %d: unsupported pairwise cipher suite '%s'",
|
||||||
|
line, pos);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
} else if (os_strcmp(buf, "group_cipher") == 0) {
|
} else if (os_strcmp(buf, "group_cipher") == 0) {
|
||||||
bss->group_cipher = hostapd_config_parse_cipher(line, pos);
|
bss->group_cipher = hostapd_config_parse_cipher(line, pos);
|
||||||
if (bss->group_cipher == -1 || bss->group_cipher == 0)
|
if (bss->group_cipher == -1 || bss->group_cipher == 0)
|
||||||
|
@ -3642,6 +3678,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
||||||
conf->use_driver_iface_addr = atoi(pos);
|
conf->use_driver_iface_addr = atoi(pos);
|
||||||
} else if (os_strcmp(buf, "ieee80211w") == 0) {
|
} else if (os_strcmp(buf, "ieee80211w") == 0) {
|
||||||
bss->ieee80211w = atoi(pos);
|
bss->ieee80211w = atoi(pos);
|
||||||
|
} else if (os_strcmp(buf, "rsn_override_mfp") == 0) {
|
||||||
|
bss->rsn_override_mfp = atoi(pos);
|
||||||
|
} else if (os_strcmp(buf, "rsn_override_mfp_2") == 0) {
|
||||||
|
bss->rsn_override_mfp_2 = atoi(pos);
|
||||||
} else if (os_strcmp(buf, "group_mgmt_cipher") == 0) {
|
} else if (os_strcmp(buf, "group_mgmt_cipher") == 0) {
|
||||||
if (os_strcmp(pos, "AES-128-CMAC") == 0) {
|
if (os_strcmp(pos, "AES-128-CMAC") == 0) {
|
||||||
bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
|
bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
|
||||||
|
|
|
@ -2298,6 +2298,58 @@ own_ip_addr=127.0.0.1
|
||||||
#
|
#
|
||||||
#ssid_protection=0
|
#ssid_protection=0
|
||||||
|
|
||||||
|
# RSNE/RSNXE override
|
||||||
|
#
|
||||||
|
# These parameters can be used to configure RSN parameters for STAs that support
|
||||||
|
# the override elements. The RSN parameters for STAs that do not support these
|
||||||
|
# mechanisms are configured in the referenced configuration parameters. The AP
|
||||||
|
# allows STAs to use either of the configured sets for negotiating RSN
|
||||||
|
# parameters.
|
||||||
|
#
|
||||||
|
# The main purpose of this mechanism is to make the AP look like it is using an
|
||||||
|
# older security mechanism (e.g., WPA2-Personal) to older STAs while allowing
|
||||||
|
# new stations use newer security mechanisms (e.g., WPA3-Personal) based on the
|
||||||
|
# override values. This might be needed to work around issues with deployed
|
||||||
|
# STAs that do not implement RSNE extensibility correctly and may fail to
|
||||||
|
# connect when the AP is using a transition mode like WPA3-Personal transition
|
||||||
|
# mode.
|
||||||
|
#
|
||||||
|
# Key management; see wpa_key_mgmt for RSNE configuration
|
||||||
|
#rsn_override_key_mgmt=<accepted key management algorithms>
|
||||||
|
#
|
||||||
|
# Pairwise cipher suites; see rsn_pairwise for RSNE configuration
|
||||||
|
#rsn_override_pairwise=<accepted cipher suites)
|
||||||
|
#
|
||||||
|
# Management frame protection (MFP/PMF); see ieee80211w for RSNE configuration
|
||||||
|
# 0 = disabled
|
||||||
|
# 1 = optional
|
||||||
|
# 2 = required
|
||||||
|
#rsn_override_mfp=<0/1/2>
|
||||||
|
#
|
||||||
|
# Second set of similar parameters. These are required to be used for
|
||||||
|
# Wi-Fi 7 (EHT/MLO) associations with RSN overriding and can optionally be used
|
||||||
|
# in cases that do not use Wi-Fi 7.
|
||||||
|
#rsn_override_key_mgmt_2
|
||||||
|
#rsn_override_pairwise_2
|
||||||
|
#rsn_override_mfp_2
|
||||||
|
#
|
||||||
|
# Example configuration for WPA2-Personal/PMF-optional in RSNE and
|
||||||
|
# WPA3-Personal/PMF-required/MLO in override elements
|
||||||
|
#wpa_key_mgmt=WPA-PSK
|
||||||
|
#rsn_pairwise=CCMP
|
||||||
|
#ieee80211w=1
|
||||||
|
#rsn_override_key_mgmt=SAE
|
||||||
|
#rsn_override_pairwise=GCMP-256
|
||||||
|
#rsn_override_mfp=2
|
||||||
|
#rsn_override_key_mgmt_2=SAE-EXT-KEY
|
||||||
|
#rsn_override_pairwise_2=GCMP-256
|
||||||
|
#rsn_override_mfp_2=2
|
||||||
|
#beacon_prot=1
|
||||||
|
#sae_groups=19 20
|
||||||
|
#sae_require_mfp=1
|
||||||
|
#sae_pwe=2
|
||||||
|
|
||||||
|
|
||||||
##### IEEE 802.11r configuration ##############################################
|
##### IEEE 802.11r configuration ##############################################
|
||||||
|
|
||||||
# Mobility Domain identifier (dot11FTMobilityDomainID, MDID)
|
# Mobility Domain identifier (dot11FTMobilityDomainID, MDID)
|
||||||
|
|
|
@ -494,10 +494,14 @@ int hostapd_setup_sae_pt(struct hostapd_bss_config *conf)
|
||||||
|
|
||||||
if ((conf->sae_pwe == SAE_PWE_HUNT_AND_PECK &&
|
if ((conf->sae_pwe == SAE_PWE_HUNT_AND_PECK &&
|
||||||
!hostapd_sae_pw_id_in_use(conf) &&
|
!hostapd_sae_pw_id_in_use(conf) &&
|
||||||
!wpa_key_mgmt_sae_ext_key(conf->wpa_key_mgmt) &&
|
!wpa_key_mgmt_sae_ext_key(conf->wpa_key_mgmt |
|
||||||
|
conf->rsn_override_key_mgmt |
|
||||||
|
conf->rsn_override_key_mgmt_2) &&
|
||||||
!hostapd_sae_pk_in_use(conf)) ||
|
!hostapd_sae_pk_in_use(conf)) ||
|
||||||
conf->sae_pwe == SAE_PWE_FORCE_HUNT_AND_PECK ||
|
conf->sae_pwe == SAE_PWE_FORCE_HUNT_AND_PECK ||
|
||||||
!wpa_key_mgmt_sae(conf->wpa_key_mgmt))
|
!wpa_key_mgmt_sae(conf->wpa_key_mgmt |
|
||||||
|
conf->rsn_override_key_mgmt |
|
||||||
|
conf->rsn_override_key_mgmt_2))
|
||||||
return 0; /* PT not needed */
|
return 0; /* PT not needed */
|
||||||
|
|
||||||
sae_deinit_pt(ssid->pt);
|
sae_deinit_pt(ssid->pt);
|
||||||
|
|
|
@ -358,7 +358,11 @@ struct hostapd_bss_config {
|
||||||
int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */
|
int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */
|
||||||
int extended_key_id;
|
int extended_key_id;
|
||||||
int wpa_key_mgmt;
|
int wpa_key_mgmt;
|
||||||
|
int rsn_override_key_mgmt;
|
||||||
|
int rsn_override_key_mgmt_2;
|
||||||
enum mfp_options ieee80211w;
|
enum mfp_options ieee80211w;
|
||||||
|
enum mfp_options rsn_override_mfp;
|
||||||
|
enum mfp_options rsn_override_mfp_2;
|
||||||
int group_mgmt_cipher;
|
int group_mgmt_cipher;
|
||||||
int beacon_prot;
|
int beacon_prot;
|
||||||
/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
|
/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
|
||||||
|
@ -387,6 +391,8 @@ struct hostapd_bss_config {
|
||||||
u32 wpa_pairwise_update_count;
|
u32 wpa_pairwise_update_count;
|
||||||
int wpa_disable_eapol_key_retries;
|
int wpa_disable_eapol_key_retries;
|
||||||
int rsn_pairwise;
|
int rsn_pairwise;
|
||||||
|
int rsn_override_pairwise;
|
||||||
|
int rsn_override_pairwise_2;
|
||||||
int rsn_preauth;
|
int rsn_preauth;
|
||||||
char *rsn_preauth_interfaces;
|
char *rsn_preauth_interfaces;
|
||||||
|
|
||||||
|
|
100
src/ap/beacon.c
100
src/ap/beacon.c
|
@ -403,6 +403,81 @@ static u8 * hostapd_get_osen_ie(struct hostapd_data *hapd, u8 *pos, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static u8 * hostapd_get_rsne_override(struct hostapd_data *hapd, u8 *pos,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
const u8 *ie;
|
||||||
|
|
||||||
|
ie = hostapd_vendor_wpa_ie(hapd, RSNE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
if (!ie || 2U + ie[1] > len)
|
||||||
|
return pos;
|
||||||
|
|
||||||
|
os_memcpy(pos, ie, 2 + ie[1]);
|
||||||
|
return pos + 2 + ie[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static u8 * hostapd_get_rsne_override_2(struct hostapd_data *hapd, u8 *pos,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
const u8 *ie;
|
||||||
|
|
||||||
|
ie = hostapd_vendor_wpa_ie(hapd, RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
|
||||||
|
if (!ie || 2U + ie[1] > len)
|
||||||
|
return pos;
|
||||||
|
|
||||||
|
os_memcpy(pos, ie, 2 + ie[1]);
|
||||||
|
return pos + 2 + ie[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static u8 * hostapd_get_rsnxe_override(struct hostapd_data *hapd, u8 *pos,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
const u8 *ie;
|
||||||
|
|
||||||
|
ie = hostapd_vendor_wpa_ie(hapd, RSNXE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
if (!ie || 2U + ie[1] > len)
|
||||||
|
return pos;
|
||||||
|
|
||||||
|
os_memcpy(pos, ie, 2 + ie[1]);
|
||||||
|
return pos + 2 + ie[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static size_t hostapd_get_rsne_override_len(struct hostapd_data *hapd)
|
||||||
|
{
|
||||||
|
const u8 *ie;
|
||||||
|
|
||||||
|
ie = hostapd_vendor_wpa_ie(hapd, RSNE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
if (!ie)
|
||||||
|
return 0;
|
||||||
|
return 2 + ie[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static size_t hostapd_get_rsne_override_2_len(struct hostapd_data *hapd)
|
||||||
|
{
|
||||||
|
const u8 *ie;
|
||||||
|
|
||||||
|
ie = hostapd_vendor_wpa_ie(hapd, RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
|
||||||
|
if (!ie)
|
||||||
|
return 0;
|
||||||
|
return 2 + ie[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static size_t hostapd_get_rsnxe_override_len(struct hostapd_data *hapd)
|
||||||
|
{
|
||||||
|
const u8 *ie;
|
||||||
|
|
||||||
|
ie = hostapd_vendor_wpa_ie(hapd, RSNXE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
if (!ie)
|
||||||
|
return 0;
|
||||||
|
return 2 + ie[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static u8 * hostapd_eid_csa(struct hostapd_data *hapd, u8 *eid)
|
static u8 * hostapd_eid_csa(struct hostapd_data *hapd, u8 *eid)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
@ -686,6 +761,9 @@ static size_t hostapd_probe_resp_elems_len(struct hostapd_data *hapd,
|
||||||
buflen += hostapd_mbo_ie_len(hapd);
|
buflen += hostapd_mbo_ie_len(hapd);
|
||||||
buflen += hostapd_eid_owe_trans_len(hapd);
|
buflen += hostapd_eid_owe_trans_len(hapd);
|
||||||
buflen += hostapd_eid_dpp_cc_len(hapd);
|
buflen += hostapd_eid_dpp_cc_len(hapd);
|
||||||
|
buflen += hostapd_get_rsne_override_len(hapd);
|
||||||
|
buflen += hostapd_get_rsne_override_2_len(hapd);
|
||||||
|
buflen += hostapd_get_rsnxe_override_len(hapd);
|
||||||
|
|
||||||
return buflen;
|
return buflen;
|
||||||
}
|
}
|
||||||
|
@ -885,6 +963,10 @@ static u8 * hostapd_probe_resp_fill_elems(struct hostapd_data *hapd,
|
||||||
pos = hostapd_eid_owe_trans(hapd, pos, epos - pos);
|
pos = hostapd_eid_owe_trans(hapd, pos, epos - pos);
|
||||||
pos = hostapd_eid_dpp_cc(hapd, pos, epos - pos);
|
pos = hostapd_eid_dpp_cc(hapd, pos, epos - pos);
|
||||||
|
|
||||||
|
pos = hostapd_get_rsne_override(hapd, pos, epos - pos);
|
||||||
|
pos = hostapd_get_rsne_override_2(hapd, pos, epos - pos);
|
||||||
|
pos = hostapd_get_rsnxe_override(hapd, pos, epos - pos);
|
||||||
|
|
||||||
if (hapd->conf->vendor_elements) {
|
if (hapd->conf->vendor_elements) {
|
||||||
os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements),
|
os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements),
|
||||||
wpabuf_len(hapd->conf->vendor_elements));
|
wpabuf_len(hapd->conf->vendor_elements));
|
||||||
|
@ -2157,6 +2239,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
||||||
tail_len += hostapd_mbo_ie_len(hapd);
|
tail_len += hostapd_mbo_ie_len(hapd);
|
||||||
tail_len += hostapd_eid_owe_trans_len(hapd);
|
tail_len += hostapd_eid_owe_trans_len(hapd);
|
||||||
tail_len += hostapd_eid_dpp_cc_len(hapd);
|
tail_len += hostapd_eid_dpp_cc_len(hapd);
|
||||||
|
tail_len += hostapd_get_rsne_override_len(hapd);
|
||||||
|
tail_len += hostapd_get_rsne_override_2_len(hapd);
|
||||||
|
tail_len += hostapd_get_rsnxe_override_len(hapd);
|
||||||
|
|
||||||
tailpos = tail = os_malloc(tail_len);
|
tailpos = tail = os_malloc(tail_len);
|
||||||
if (head == NULL || tail == NULL) {
|
if (head == NULL || tail == NULL) {
|
||||||
|
@ -2368,6 +2453,13 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
||||||
tail + tail_len - tailpos);
|
tail + tail_len - tailpos);
|
||||||
tailpos = hostapd_eid_dpp_cc(hapd, tailpos, tail + tail_len - tailpos);
|
tailpos = hostapd_eid_dpp_cc(hapd, tailpos, tail + tail_len - tailpos);
|
||||||
|
|
||||||
|
tailpos = hostapd_get_rsne_override(hapd, tailpos,
|
||||||
|
tail + tail_len - tailpos);
|
||||||
|
tailpos = hostapd_get_rsne_override_2(hapd, tailpos,
|
||||||
|
tail + tail_len - tailpos);
|
||||||
|
tailpos = hostapd_get_rsnxe_override(hapd, tailpos,
|
||||||
|
tail + tail_len - tailpos);
|
||||||
|
|
||||||
if (hapd->conf->vendor_elements) {
|
if (hapd->conf->vendor_elements) {
|
||||||
os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements),
|
os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements),
|
||||||
wpabuf_len(hapd->conf->vendor_elements));
|
wpabuf_len(hapd->conf->vendor_elements));
|
||||||
|
@ -2400,7 +2492,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
||||||
/* If SAE offload is enabled, provide password to lower layer for
|
/* If SAE offload is enabled, provide password to lower layer for
|
||||||
* SAE authentication and PMK generation.
|
* SAE authentication and PMK generation.
|
||||||
*/
|
*/
|
||||||
if (wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
|
if (wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt |
|
||||||
|
hapd->conf->rsn_override_key_mgmt |
|
||||||
|
hapd->conf->rsn_override_key_mgmt_2) &&
|
||||||
(hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_AP)) {
|
(hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_AP)) {
|
||||||
if (hostapd_sae_pk_in_use(hapd->conf)) {
|
if (hostapd_sae_pk_in_use(hapd->conf)) {
|
||||||
wpa_printf(MSG_ERROR,
|
wpa_printf(MSG_ERROR,
|
||||||
|
@ -2445,7 +2539,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
||||||
else if (hapd->conf->wpa & WPA_PROTO_WPA)
|
else if (hapd->conf->wpa & WPA_PROTO_WPA)
|
||||||
params->pairwise_ciphers = hapd->conf->wpa_pairwise;
|
params->pairwise_ciphers = hapd->conf->wpa_pairwise;
|
||||||
params->group_cipher = hapd->conf->wpa_group;
|
params->group_cipher = hapd->conf->wpa_group;
|
||||||
params->key_mgmt_suites = hapd->conf->wpa_key_mgmt;
|
params->key_mgmt_suites = hapd->conf->wpa_key_mgmt |
|
||||||
|
hapd->conf->rsn_override_key_mgmt |
|
||||||
|
hapd->conf->rsn_override_key_mgmt_2;
|
||||||
params->auth_algs = hapd->conf->auth_algs;
|
params->auth_algs = hapd->conf->auth_algs;
|
||||||
params->wpa_version = hapd->conf->wpa;
|
params->wpa_version = hapd->conf->wpa;
|
||||||
params->privacy = hapd->conf->wpa;
|
params->privacy = hapd->conf->wpa;
|
||||||
|
|
|
@ -513,6 +513,10 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
||||||
"Failed to initialize WPA state machine");
|
"Failed to initialize WPA state machine");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
wpa_auth_set_rsn_override(sta->wpa_sm,
|
||||||
|
elems.rsne_override != NULL);
|
||||||
|
wpa_auth_set_rsn_override_2(sta->wpa_sm,
|
||||||
|
elems.rsne_override_2 != NULL);
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
if (ap_sta_is_mld(hapd, sta)) {
|
if (ap_sta_is_mld(hapd, sta)) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
|
|
|
@ -1945,6 +1945,9 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
if (resp != WLAN_STATUS_SUCCESS)
|
if (resp != WLAN_STATUS_SUCCESS)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
wpa_auth_set_rsn_override(sta->wpa_sm, elems.rsne_override != NULL);
|
||||||
|
wpa_auth_set_rsn_override_2(sta->wpa_sm, elems.rsne_override_2 != NULL);
|
||||||
|
|
||||||
if (!elems.fils_nonce) {
|
if (!elems.fils_nonce) {
|
||||||
wpa_printf(MSG_DEBUG, "FILS: No FILS Nonce field");
|
wpa_printf(MSG_DEBUG, "FILS: No FILS Nonce field");
|
||||||
resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||||
|
@ -2961,7 +2964,10 @@ static void handle_auth(struct hostapd_data *hapd,
|
||||||
auth_alg == WLAN_AUTH_FT) ||
|
auth_alg == WLAN_AUTH_FT) ||
|
||||||
#endif /* CONFIG_IEEE80211R_AP */
|
#endif /* CONFIG_IEEE80211R_AP */
|
||||||
#ifdef CONFIG_SAE
|
#ifdef CONFIG_SAE
|
||||||
(hapd->conf->wpa && wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
|
(hapd->conf->wpa &&
|
||||||
|
wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt |
|
||||||
|
hapd->conf->rsn_override_key_mgmt |
|
||||||
|
hapd->conf->rsn_override_key_mgmt_2) &&
|
||||||
auth_alg == WLAN_AUTH_SAE) ||
|
auth_alg == WLAN_AUTH_SAE) ||
|
||||||
#endif /* CONFIG_SAE */
|
#endif /* CONFIG_SAE */
|
||||||
#ifdef CONFIG_FILS
|
#ifdef CONFIG_FILS
|
||||||
|
@ -4128,6 +4134,10 @@ static int __check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
wpa_auth_set_auth_alg(sta->wpa_sm, sta->auth_alg);
|
wpa_auth_set_auth_alg(sta->wpa_sm, sta->auth_alg);
|
||||||
|
wpa_auth_set_rsn_override(sta->wpa_sm,
|
||||||
|
elems->rsne_override != NULL);
|
||||||
|
wpa_auth_set_rsn_override_2(sta->wpa_sm,
|
||||||
|
elems->rsne_override_2 != NULL);
|
||||||
res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
|
res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
|
||||||
hapd->iface->freq,
|
hapd->iface->freq,
|
||||||
wpa_ie, wpa_ie_len,
|
wpa_ie, wpa_ie_len,
|
||||||
|
|
|
@ -885,6 +885,9 @@ void wpa_deinit(struct wpa_authenticator *wpa_auth)
|
||||||
|
|
||||||
|
|
||||||
os_free(wpa_auth->wpa_ie);
|
os_free(wpa_auth->wpa_ie);
|
||||||
|
os_free(wpa_auth->rsne_override);
|
||||||
|
os_free(wpa_auth->rsne_override_2);
|
||||||
|
os_free(wpa_auth->rsnxe_override);
|
||||||
|
|
||||||
group = wpa_auth->group;
|
group = wpa_auth->group;
|
||||||
while (group) {
|
while (group) {
|
||||||
|
@ -4449,7 +4452,7 @@ static size_t wpa_auth_ml_kdes_len(struct wpa_state_machine *sm)
|
||||||
/* MLO Link KDE for each link */
|
/* MLO Link KDE for each link */
|
||||||
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
|
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
|
||||||
struct wpa_authenticator *wpa_auth;
|
struct wpa_authenticator *wpa_auth;
|
||||||
const u8 *ie;
|
const u8 *ie, *ieo;
|
||||||
|
|
||||||
wpa_auth = wpa_get_link_auth(sm->wpa_auth, link_id);
|
wpa_auth = wpa_get_link_auth(sm->wpa_auth, link_id);
|
||||||
if (!wpa_auth)
|
if (!wpa_auth)
|
||||||
|
@ -4458,11 +4461,22 @@ static size_t wpa_auth_ml_kdes_len(struct wpa_state_machine *sm)
|
||||||
kde_len += 2 + RSN_SELECTOR_LEN + 1 + ETH_ALEN;
|
kde_len += 2 + RSN_SELECTOR_LEN + 1 + ETH_ALEN;
|
||||||
ie = get_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
|
ie = get_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
|
||||||
WLAN_EID_RSN);
|
WLAN_EID_RSN);
|
||||||
if (ie)
|
ieo = get_vendor_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
|
||||||
|
sm->rsn_override_2 ?
|
||||||
|
RSNE_OVERRIDE_2_IE_VENDOR_TYPE :
|
||||||
|
RSNE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
if ((sm->rsn_override || sm->rsn_override_2) && ieo)
|
||||||
|
kde_len += 2 + ieo[1 - 4];
|
||||||
|
else
|
||||||
kde_len += 2 + ie[1];
|
kde_len += 2 + ie[1];
|
||||||
|
|
||||||
ie = get_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
|
ie = get_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
|
||||||
WLAN_EID_RSNX);
|
WLAN_EID_RSNX);
|
||||||
if (ie)
|
ieo = get_vendor_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
|
||||||
|
RSNXE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
if ((sm->rsn_override || sm->rsn_override_2) && ieo)
|
||||||
|
kde_len += 2 + ieo[1] - 4;
|
||||||
|
else if (ie)
|
||||||
kde_len += 2 + ie[1];
|
kde_len += 2 + ie[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4488,7 +4502,7 @@ static u8 * wpa_auth_ml_kdes(struct wpa_state_machine *sm, u8 *pos)
|
||||||
|
|
||||||
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
|
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
|
||||||
struct wpa_authenticator *wpa_auth;
|
struct wpa_authenticator *wpa_auth;
|
||||||
const u8 *rsne, *rsnxe;
|
const u8 *rsne, *rsnxe, *rsneo, *rsnxeo;
|
||||||
size_t rsne_len, rsnxe_len;
|
size_t rsne_len, rsnxe_len;
|
||||||
|
|
||||||
wpa_auth = wpa_get_link_auth(sm->wpa_auth, link_id);
|
wpa_auth = wpa_get_link_auth(sm->wpa_auth, link_id);
|
||||||
|
@ -4498,10 +4512,24 @@ static u8 * wpa_auth_ml_kdes(struct wpa_state_machine *sm, u8 *pos)
|
||||||
rsne = get_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
|
rsne = get_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
|
||||||
WLAN_EID_RSN);
|
WLAN_EID_RSN);
|
||||||
rsne_len = rsne ? 2 + rsne[1] : 0;
|
rsne_len = rsne ? 2 + rsne[1] : 0;
|
||||||
|
rsneo = get_vendor_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
|
||||||
|
sm->rsn_override_2 ?
|
||||||
|
RSNE_OVERRIDE_2_IE_VENDOR_TYPE :
|
||||||
|
RSNE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
if ((sm->rsn_override || sm->rsn_override_2) && rsneo)
|
||||||
|
rsne_len = 2 + rsneo[1] - 4;
|
||||||
|
else
|
||||||
|
rsneo = NULL;
|
||||||
|
|
||||||
rsnxe = get_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
|
rsnxe = get_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
|
||||||
WLAN_EID_RSNX);
|
WLAN_EID_RSNX);
|
||||||
rsnxe_len = rsnxe ? 2 + rsnxe[1] : 0;
|
rsnxe_len = rsnxe ? 2 + rsnxe[1] : 0;
|
||||||
|
rsnxeo = get_vendor_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
|
||||||
|
RSNXE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
if ((sm->rsn_override || sm->rsn_override_2) && rsnxeo)
|
||||||
|
rsnxe_len = 2 + rsnxeo[1] - 4;
|
||||||
|
else
|
||||||
|
rsnxeo = NULL;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"RSN: MLO Link: link=%u, len=%zu", link_id,
|
"RSN: MLO Link: link=%u, len=%zu", link_id,
|
||||||
|
@ -4527,13 +4555,27 @@ static u8 * wpa_auth_ml_kdes(struct wpa_state_machine *sm, u8 *pos)
|
||||||
pos += ETH_ALEN;
|
pos += ETH_ALEN;
|
||||||
|
|
||||||
if (rsne_len) {
|
if (rsne_len) {
|
||||||
os_memcpy(pos, rsne, rsne_len);
|
if (rsneo) {
|
||||||
pos += rsne_len;
|
*pos++ = WLAN_EID_RSN;
|
||||||
|
*pos++ = rsneo[1] - 4;
|
||||||
|
os_memcpy(pos, &rsneo[2 + 4], rsneo[1] - 4);
|
||||||
|
pos += rsneo[1] - 4;
|
||||||
|
} else {
|
||||||
|
os_memcpy(pos, rsne, rsne_len);
|
||||||
|
pos += rsne_len;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rsnxe_len) {
|
if (rsnxe_len) {
|
||||||
os_memcpy(pos, rsnxe, rsnxe_len);
|
if (rsnxeo) {
|
||||||
pos += rsnxe_len;
|
*pos++ = WLAN_EID_RSNX;
|
||||||
|
*pos++ = rsnxeo[1] - 4;
|
||||||
|
os_memcpy(pos, &rsnxeo[2 + 4], rsnxeo[1] - 4);
|
||||||
|
pos += rsnxeo[1] - 4;
|
||||||
|
} else {
|
||||||
|
os_memcpy(pos, rsnxe, rsnxe_len);
|
||||||
|
pos += rsnxe_len;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4552,7 +4594,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
|
||||||
struct wpa_group *gsm = sm->group;
|
struct wpa_group *gsm = sm->group;
|
||||||
u8 *wpa_ie;
|
u8 *wpa_ie;
|
||||||
int secure, gtkidx, encr = 0;
|
int secure, gtkidx, encr = 0;
|
||||||
u8 *wpa_ie_buf = NULL, *wpa_ie_buf2 = NULL;
|
u8 *wpa_ie_buf = NULL, *wpa_ie_buf2 = NULL, *wpa_ie_buf3 = NULL;
|
||||||
u8 hdr[2];
|
u8 hdr[2];
|
||||||
struct wpa_auth_config *conf = &sm->wpa_auth->conf;
|
struct wpa_auth_config *conf = &sm->wpa_auth->conf;
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
@ -4593,6 +4635,80 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
|
||||||
wpa_ie = wpa_ie + wpa_ie[1] + 2;
|
wpa_ie = wpa_ie + wpa_ie[1] + 2;
|
||||||
wpa_ie_len = wpa_ie[1] + 2;
|
wpa_ie_len = wpa_ie[1] + 2;
|
||||||
}
|
}
|
||||||
|
if ((sm->rsn_override &&
|
||||||
|
get_vendor_ie(wpa_ie, wpa_ie_len, RSNE_OVERRIDE_IE_VENDOR_TYPE)) ||
|
||||||
|
(sm->rsn_override_2 &&
|
||||||
|
get_vendor_ie(wpa_ie, wpa_ie_len,
|
||||||
|
RSNE_OVERRIDE_2_IE_VENDOR_TYPE))) {
|
||||||
|
const u8 *mde, *fte, *tie, *tie2 = NULL;
|
||||||
|
const u8 *override_rsne = NULL, *override_rsnxe = NULL;
|
||||||
|
const struct element *elem;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"RSN: Use RSNE/RSNXE override element contents");
|
||||||
|
mde = get_ie(wpa_ie, wpa_ie_len, WLAN_EID_MOBILITY_DOMAIN);
|
||||||
|
fte = get_ie(wpa_ie, wpa_ie_len, WLAN_EID_FAST_BSS_TRANSITION);
|
||||||
|
tie = get_ie(wpa_ie, wpa_ie_len, WLAN_EID_TIMEOUT_INTERVAL);
|
||||||
|
if (tie) {
|
||||||
|
const u8 *next = tie + 2 + tie[1];
|
||||||
|
|
||||||
|
tie2 = get_ie(next, wpa_ie + wpa_ie_len - next,
|
||||||
|
WLAN_EID_TIMEOUT_INTERVAL);
|
||||||
|
}
|
||||||
|
for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC,
|
||||||
|
wpa_ie, wpa_ie_len) {
|
||||||
|
if (elem->datalen >= 4) {
|
||||||
|
if (WPA_GET_BE32(elem->data) ==
|
||||||
|
(sm->rsn_override_2 ?
|
||||||
|
RSNE_OVERRIDE_2_IE_VENDOR_TYPE :
|
||||||
|
RSNE_OVERRIDE_IE_VENDOR_TYPE))
|
||||||
|
override_rsne = &elem->id;
|
||||||
|
if (WPA_GET_BE32(elem->data) ==
|
||||||
|
RSNXE_OVERRIDE_IE_VENDOR_TYPE)
|
||||||
|
override_rsnxe = &elem->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wpa_hexdump(MSG_DEBUG, "EAPOL-Key msg 3/4 IEs before edits",
|
||||||
|
wpa_ie, wpa_ie_len);
|
||||||
|
wpa_ie_buf3 = os_malloc(wpa_ie_len);
|
||||||
|
if (!wpa_ie_buf3)
|
||||||
|
goto done;
|
||||||
|
pos = wpa_ie_buf3;
|
||||||
|
if (override_rsne) {
|
||||||
|
*pos++ = WLAN_EID_RSN;
|
||||||
|
*pos++ = override_rsne[1] - 4;
|
||||||
|
os_memcpy(pos, &override_rsne[2 + 4],
|
||||||
|
override_rsne[1] - 4);
|
||||||
|
pos += override_rsne[1] - 4;
|
||||||
|
}
|
||||||
|
if (mde) {
|
||||||
|
os_memcpy(pos, mde, 2 + mde[1]);
|
||||||
|
pos += 2 + mde[1];
|
||||||
|
}
|
||||||
|
if (fte) {
|
||||||
|
os_memcpy(pos, fte, 2 + fte[1]);
|
||||||
|
pos += 2 + fte[1];
|
||||||
|
}
|
||||||
|
if (tie) {
|
||||||
|
os_memcpy(pos, tie, 2 + tie[1]);
|
||||||
|
pos += 2 + tie[1];
|
||||||
|
}
|
||||||
|
if (tie2) {
|
||||||
|
os_memcpy(pos, tie2, 2 + tie2[1]);
|
||||||
|
pos += 2 + tie2[1];
|
||||||
|
}
|
||||||
|
if (override_rsnxe) {
|
||||||
|
*pos++ = WLAN_EID_RSNX;
|
||||||
|
*pos++ = override_rsnxe[1] - 4;
|
||||||
|
os_memcpy(pos, &override_rsnxe[2 + 4],
|
||||||
|
override_rsnxe[1] - 4);
|
||||||
|
pos += override_rsnxe[1] - 4;
|
||||||
|
}
|
||||||
|
wpa_ie = wpa_ie_buf3;
|
||||||
|
wpa_ie_len = pos - wpa_ie_buf3;
|
||||||
|
wpa_hexdump(MSG_DEBUG, "EAPOL-Key msg 3/4 IEs after edits",
|
||||||
|
wpa_ie, wpa_ie_len);
|
||||||
|
}
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
if (conf->rsne_override_eapol_set) {
|
if (conf->rsne_override_eapol_set) {
|
||||||
wpa_ie_buf2 = replace_ie(
|
wpa_ie_buf2 = replace_ie(
|
||||||
|
@ -4862,6 +4978,7 @@ done:
|
||||||
bin_clear_free(kde, kde_len);
|
bin_clear_free(kde, kde_len);
|
||||||
os_free(wpa_ie_buf);
|
os_free(wpa_ie_buf);
|
||||||
os_free(wpa_ie_buf2);
|
os_free(wpa_ie_buf2);
|
||||||
|
os_free(wpa_ie_buf3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -6813,6 +6930,20 @@ void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wpa_auth_set_rsn_override(struct wpa_state_machine *sm, bool val)
|
||||||
|
{
|
||||||
|
if (sm)
|
||||||
|
sm->rsn_override = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wpa_auth_set_rsn_override_2(struct wpa_state_machine *sm, bool val)
|
||||||
|
{
|
||||||
|
if (sm)
|
||||||
|
sm->rsn_override_2 = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_DPP2
|
#ifdef CONFIG_DPP2
|
||||||
void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z)
|
void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z)
|
||||||
{
|
{
|
||||||
|
|
|
@ -173,6 +173,8 @@ struct wpa_auth_config {
|
||||||
int wpa;
|
int wpa;
|
||||||
int extended_key_id;
|
int extended_key_id;
|
||||||
int wpa_key_mgmt;
|
int wpa_key_mgmt;
|
||||||
|
int rsn_override_key_mgmt;
|
||||||
|
int rsn_override_key_mgmt_2;
|
||||||
int wpa_pairwise;
|
int wpa_pairwise;
|
||||||
int wpa_group;
|
int wpa_group;
|
||||||
int wpa_group_rekey;
|
int wpa_group_rekey;
|
||||||
|
@ -184,6 +186,8 @@ struct wpa_auth_config {
|
||||||
u32 wpa_pairwise_update_count;
|
u32 wpa_pairwise_update_count;
|
||||||
int wpa_disable_eapol_key_retries;
|
int wpa_disable_eapol_key_retries;
|
||||||
int rsn_pairwise;
|
int rsn_pairwise;
|
||||||
|
int rsn_override_pairwise;
|
||||||
|
int rsn_override_pairwise_2;
|
||||||
int rsn_preauth;
|
int rsn_preauth;
|
||||||
int eapol_version;
|
int eapol_version;
|
||||||
int wmm_enabled;
|
int wmm_enabled;
|
||||||
|
@ -192,6 +196,8 @@ struct wpa_auth_config {
|
||||||
int okc;
|
int okc;
|
||||||
int tx_status;
|
int tx_status;
|
||||||
enum mfp_options ieee80211w;
|
enum mfp_options ieee80211w;
|
||||||
|
enum mfp_options rsn_override_mfp;
|
||||||
|
enum mfp_options rsn_override_mfp_2;
|
||||||
int beacon_prot;
|
int beacon_prot;
|
||||||
int group_mgmt_cipher;
|
int group_mgmt_cipher;
|
||||||
int sae_require_mfp;
|
int sae_require_mfp;
|
||||||
|
@ -605,6 +611,8 @@ u8 * wpa_auth_write_assoc_resp_fils(struct wpa_state_machine *sm,
|
||||||
bool wpa_auth_write_fd_rsn_info(struct wpa_authenticator *wpa_auth,
|
bool wpa_auth_write_fd_rsn_info(struct wpa_authenticator *wpa_auth,
|
||||||
u8 *fd_rsn_info);
|
u8 *fd_rsn_info);
|
||||||
void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg);
|
void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg);
|
||||||
|
void wpa_auth_set_rsn_override(struct wpa_state_machine *sm, bool val);
|
||||||
|
void wpa_auth_set_rsn_override_2(struct wpa_state_machine *sm, bool val);
|
||||||
void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z);
|
void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z);
|
||||||
void wpa_auth_set_ssid_protection(struct wpa_state_machine *sm, bool val);
|
void wpa_auth_set_ssid_protection(struct wpa_state_machine *sm, bool val);
|
||||||
void wpa_auth_set_transition_disable(struct wpa_authenticator *wpa_auth,
|
void wpa_auth_set_transition_disable(struct wpa_authenticator *wpa_auth,
|
||||||
|
|
|
@ -45,6 +45,8 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
||||||
wconf->wpa = conf->wpa;
|
wconf->wpa = conf->wpa;
|
||||||
wconf->extended_key_id = conf->extended_key_id;
|
wconf->extended_key_id = conf->extended_key_id;
|
||||||
wconf->wpa_key_mgmt = conf->wpa_key_mgmt;
|
wconf->wpa_key_mgmt = conf->wpa_key_mgmt;
|
||||||
|
wconf->rsn_override_key_mgmt = conf->rsn_override_key_mgmt;
|
||||||
|
wconf->rsn_override_key_mgmt_2 = conf->rsn_override_key_mgmt_2;
|
||||||
wconf->wpa_pairwise = conf->wpa_pairwise;
|
wconf->wpa_pairwise = conf->wpa_pairwise;
|
||||||
wconf->wpa_group = conf->wpa_group;
|
wconf->wpa_group = conf->wpa_group;
|
||||||
wconf->wpa_group_rekey = conf->wpa_group_rekey;
|
wconf->wpa_group_rekey = conf->wpa_group_rekey;
|
||||||
|
@ -56,6 +58,8 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
||||||
conf->wpa_disable_eapol_key_retries;
|
conf->wpa_disable_eapol_key_retries;
|
||||||
wconf->wpa_pairwise_update_count = conf->wpa_pairwise_update_count;
|
wconf->wpa_pairwise_update_count = conf->wpa_pairwise_update_count;
|
||||||
wconf->rsn_pairwise = conf->rsn_pairwise;
|
wconf->rsn_pairwise = conf->rsn_pairwise;
|
||||||
|
wconf->rsn_override_pairwise = conf->rsn_override_pairwise;
|
||||||
|
wconf->rsn_override_pairwise_2 = conf->rsn_override_pairwise_2;
|
||||||
wconf->rsn_preauth = conf->rsn_preauth;
|
wconf->rsn_preauth = conf->rsn_preauth;
|
||||||
wconf->eapol_version = conf->eapol_version;
|
wconf->eapol_version = conf->eapol_version;
|
||||||
#ifdef CONFIG_MACSEC
|
#ifdef CONFIG_MACSEC
|
||||||
|
@ -70,6 +74,8 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
|
||||||
#endif /* CONFIG_OCV */
|
#endif /* CONFIG_OCV */
|
||||||
wconf->okc = conf->okc;
|
wconf->okc = conf->okc;
|
||||||
wconf->ieee80211w = conf->ieee80211w;
|
wconf->ieee80211w = conf->ieee80211w;
|
||||||
|
wconf->rsn_override_mfp = conf->rsn_override_mfp;
|
||||||
|
wconf->rsn_override_mfp_2 = conf->rsn_override_mfp_2;
|
||||||
wconf->beacon_prot = conf->beacon_prot;
|
wconf->beacon_prot = conf->beacon_prot;
|
||||||
wconf->group_mgmt_cipher = conf->group_mgmt_cipher;
|
wconf->group_mgmt_cipher = conf->group_mgmt_cipher;
|
||||||
wconf->sae_require_mfp = conf->sae_require_mfp;
|
wconf->sae_require_mfp = conf->sae_require_mfp;
|
||||||
|
|
|
@ -124,6 +124,9 @@ struct wpa_state_machine {
|
||||||
u32 dot11RSNAStatsTKIPLocalMICFailures;
|
u32 dot11RSNAStatsTKIPLocalMICFailures;
|
||||||
u32 dot11RSNAStatsTKIPRemoteMICFailures;
|
u32 dot11RSNAStatsTKIPRemoteMICFailures;
|
||||||
|
|
||||||
|
bool rsn_override;
|
||||||
|
bool rsn_override_2;
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211R_AP
|
#ifdef CONFIG_IEEE80211R_AP
|
||||||
u8 xxkey[PMK_LEN_MAX]; /* PSK or the second 256 bits of MSK, or the
|
u8 xxkey[PMK_LEN_MAX]; /* PSK or the second 256 bits of MSK, or the
|
||||||
* first 384 bits of MSK */
|
* first 384 bits of MSK */
|
||||||
|
@ -248,6 +251,9 @@ struct wpa_authenticator {
|
||||||
|
|
||||||
u8 *wpa_ie;
|
u8 *wpa_ie;
|
||||||
size_t wpa_ie_len;
|
size_t wpa_ie_len;
|
||||||
|
u8 *rsne_override; /* RSNE with overridden payload */
|
||||||
|
u8 *rsne_override_2; /* RSNE with overridden (2) payload */
|
||||||
|
u8 *rsnxe_override; /* RSNXE with overridden payload */
|
||||||
|
|
||||||
u8 addr[ETH_ALEN];
|
u8 addr[ETH_ALEN];
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,8 @@ static int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static u16 wpa_own_rsn_capab(struct wpa_auth_config *conf)
|
static u16 wpa_own_rsn_capab(struct wpa_auth_config *conf,
|
||||||
|
enum mfp_options mfp)
|
||||||
{
|
{
|
||||||
u16 capab = 0;
|
u16 capab = 0;
|
||||||
|
|
||||||
|
@ -99,9 +100,9 @@ static u16 wpa_own_rsn_capab(struct wpa_auth_config *conf)
|
||||||
/* 4 PTKSA replay counters when using WMM */
|
/* 4 PTKSA replay counters when using WMM */
|
||||||
capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
|
capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
|
||||||
}
|
}
|
||||||
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
|
if (mfp != NO_MGMT_FRAME_PROTECTION) {
|
||||||
capab |= WPA_CAPABILITY_MFPC;
|
capab |= WPA_CAPABILITY_MFPC;
|
||||||
if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
|
if (mfp == MGMT_FRAME_PROTECTION_REQUIRED)
|
||||||
capab |= WPA_CAPABILITY_MFPR;
|
capab |= WPA_CAPABILITY_MFPR;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_OCV
|
#ifdef CONFIG_OCV
|
||||||
|
@ -119,24 +120,19 @@ static u16 wpa_own_rsn_capab(struct wpa_auth_config *conf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
static u8 * rsne_write_data(u8 *buf, size_t len, u8 *pos, int group,
|
||||||
const u8 *pmkid)
|
int pairwise, int key_mgmt, u16 rsn_capab,
|
||||||
|
const u8 *pmkid, enum mfp_options mfp,
|
||||||
|
int group_mgmt_cipher)
|
||||||
{
|
{
|
||||||
struct rsn_ie_hdr *hdr;
|
|
||||||
int num_suites, res;
|
int num_suites, res;
|
||||||
u8 *pos, *count;
|
u8 *count;
|
||||||
u32 suite;
|
u32 suite;
|
||||||
|
|
||||||
hdr = (struct rsn_ie_hdr *) buf;
|
suite = wpa_cipher_to_suite(WPA_PROTO_RSN, group);
|
||||||
hdr->elem_id = WLAN_EID_RSN;
|
|
||||||
WPA_PUT_LE16(hdr->version, RSN_VERSION);
|
|
||||||
pos = (u8 *) (hdr + 1);
|
|
||||||
|
|
||||||
suite = wpa_cipher_to_suite(WPA_PROTO_RSN, conf->wpa_group);
|
|
||||||
if (suite == 0) {
|
if (suite == 0) {
|
||||||
wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).",
|
wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).", group);
|
||||||
conf->wpa_group);
|
return NULL;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
RSN_SELECTOR_PUT(pos, suite);
|
RSN_SELECTOR_PUT(pos, suite);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
|
@ -153,7 +149,7 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_RSN_TESTING */
|
#endif /* CONFIG_RSN_TESTING */
|
||||||
|
|
||||||
res = rsn_cipher_put_suites(pos, conf->rsn_pairwise);
|
res = rsn_cipher_put_suites(pos, pairwise);
|
||||||
num_suites += res;
|
num_suites += res;
|
||||||
pos += res * RSN_SELECTOR_LEN;
|
pos += res * RSN_SELECTOR_LEN;
|
||||||
|
|
||||||
|
@ -167,8 +163,8 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||||
|
|
||||||
if (num_suites == 0) {
|
if (num_suites == 0) {
|
||||||
wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).",
|
wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).",
|
||||||
conf->rsn_pairwise);
|
pairwise);
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
WPA_PUT_LE16(count, num_suites);
|
WPA_PUT_LE16(count, num_suites);
|
||||||
|
|
||||||
|
@ -184,102 +180,102 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_RSN_TESTING */
|
#endif /* CONFIG_RSN_TESTING */
|
||||||
|
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
|
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
|
if (key_mgmt & WPA_KEY_MGMT_PSK) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_IEEE80211R_AP
|
#ifdef CONFIG_IEEE80211R_AP
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
|
if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_SHA384
|
#ifdef CONFIG_SHA384
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) {
|
if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_SHA384 */
|
#endif /* CONFIG_SHA384 */
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
|
if (key_mgmt & WPA_KEY_MGMT_FT_PSK) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211R_AP */
|
#endif /* CONFIG_IEEE80211R_AP */
|
||||||
#ifdef CONFIG_SHA384
|
#ifdef CONFIG_SHA384
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) {
|
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA384);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA384);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_SHA384 */
|
#endif /* CONFIG_SHA384 */
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
|
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
|
if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_SAE
|
#ifdef CONFIG_SAE
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
|
if (key_mgmt & WPA_KEY_MGMT_SAE) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
|
if (key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE_EXT_KEY);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE_EXT_KEY);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
|
if (key_mgmt & WPA_KEY_MGMT_FT_SAE) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
|
if (key_mgmt & WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE_EXT_KEY);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE_EXT_KEY);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_SAE */
|
#endif /* CONFIG_SAE */
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
|
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
|
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_FILS
|
#ifdef CONFIG_FILS
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
|
if (key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FILS_SHA256);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FILS_SHA256);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
|
if (key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FILS_SHA384);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FILS_SHA384);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_IEEE80211R_AP
|
#ifdef CONFIG_IEEE80211R_AP
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
|
if (key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA256);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA256);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
|
if (key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA384);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA384);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
|
@ -287,28 +283,28 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||||
#endif /* CONFIG_IEEE80211R_AP */
|
#endif /* CONFIG_IEEE80211R_AP */
|
||||||
#endif /* CONFIG_FILS */
|
#endif /* CONFIG_FILS */
|
||||||
#ifdef CONFIG_OWE
|
#ifdef CONFIG_OWE
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) {
|
if (key_mgmt & WPA_KEY_MGMT_OWE) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OWE);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OWE);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_OWE */
|
#endif /* CONFIG_OWE */
|
||||||
#ifdef CONFIG_DPP
|
#ifdef CONFIG_DPP
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) {
|
if (key_mgmt & WPA_KEY_MGMT_DPP) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_DPP);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_DPP);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_DPP */
|
#endif /* CONFIG_DPP */
|
||||||
#ifdef CONFIG_HS20
|
#ifdef CONFIG_HS20
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_OSEN) {
|
if (key_mgmt & WPA_KEY_MGMT_OSEN) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OSEN);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OSEN);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_HS20 */
|
#endif /* CONFIG_HS20 */
|
||||||
#ifdef CONFIG_PASN
|
#ifdef CONFIG_PASN
|
||||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PASN) {
|
if (key_mgmt & WPA_KEY_MGMT_PASN) {
|
||||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PASN);
|
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PASN);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
num_suites++;
|
num_suites++;
|
||||||
|
@ -325,18 +321,18 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||||
|
|
||||||
if (num_suites == 0) {
|
if (num_suites == 0) {
|
||||||
wpa_printf(MSG_DEBUG, "Invalid key management type (%d).",
|
wpa_printf(MSG_DEBUG, "Invalid key management type (%d).",
|
||||||
conf->wpa_key_mgmt);
|
key_mgmt);
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
WPA_PUT_LE16(count, num_suites);
|
WPA_PUT_LE16(count, num_suites);
|
||||||
|
|
||||||
/* RSN Capabilities */
|
/* RSN Capabilities */
|
||||||
WPA_PUT_LE16(pos, wpa_own_rsn_capab(conf));
|
WPA_PUT_LE16(pos, rsn_capab);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
|
|
||||||
if (pmkid) {
|
if (pmkid) {
|
||||||
if (2 + PMKID_LEN > buf + len - pos)
|
if (2 + PMKID_LEN > buf + len - pos)
|
||||||
return -1;
|
return NULL;
|
||||||
/* PMKID Count */
|
/* PMKID Count */
|
||||||
WPA_PUT_LE16(pos, 1);
|
WPA_PUT_LE16(pos, 1);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
|
@ -344,18 +340,19 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||||
pos += PMKID_LEN;
|
pos += PMKID_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION &&
|
|
||||||
conf->group_mgmt_cipher != WPA_CIPHER_AES_128_CMAC) {
|
if (mfp != NO_MGMT_FRAME_PROTECTION &&
|
||||||
|
group_mgmt_cipher != WPA_CIPHER_AES_128_CMAC) {
|
||||||
if (2 + 4 > buf + len - pos)
|
if (2 + 4 > buf + len - pos)
|
||||||
return -1;
|
return NULL;
|
||||||
if (pmkid == NULL) {
|
if (!pmkid) {
|
||||||
/* PMKID Count */
|
/* PMKID Count */
|
||||||
WPA_PUT_LE16(pos, 0);
|
WPA_PUT_LE16(pos, 0);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Management Group Cipher Suite */
|
/* Management Group Cipher Suite */
|
||||||
switch (conf->group_mgmt_cipher) {
|
switch (group_mgmt_cipher) {
|
||||||
case WPA_CIPHER_AES_128_CMAC:
|
case WPA_CIPHER_AES_128_CMAC:
|
||||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
|
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
|
||||||
break;
|
break;
|
||||||
|
@ -371,8 +368,8 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||||
default:
|
default:
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"Invalid group management cipher (0x%x)",
|
"Invalid group management cipher (0x%x)",
|
||||||
conf->group_mgmt_cipher);
|
group_mgmt_cipher);
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
}
|
}
|
||||||
|
@ -384,12 +381,12 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||||
* the element.
|
* the element.
|
||||||
*/
|
*/
|
||||||
int pmkid_count_set = pmkid != NULL;
|
int pmkid_count_set = pmkid != NULL;
|
||||||
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION)
|
if (mfp != NO_MGMT_FRAME_PROTECTION)
|
||||||
pmkid_count_set = 1;
|
pmkid_count_set = 1;
|
||||||
/* PMKID Count */
|
/* PMKID Count */
|
||||||
WPA_PUT_LE16(pos, 0);
|
WPA_PUT_LE16(pos, 0);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
if (conf->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
|
if (mfp == NO_MGMT_FRAME_PROTECTION) {
|
||||||
/* Management Group Cipher Suite */
|
/* Management Group Cipher Suite */
|
||||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
|
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
|
||||||
pos += RSN_SELECTOR_LEN;
|
pos += RSN_SELECTOR_LEN;
|
||||||
|
@ -399,6 +396,27 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||||
pos += 17;
|
pos += 17;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_RSN_TESTING */
|
#endif /* CONFIG_RSN_TESTING */
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||||
|
const u8 *pmkid)
|
||||||
|
{
|
||||||
|
struct rsn_ie_hdr *hdr;
|
||||||
|
u8 *pos;
|
||||||
|
|
||||||
|
hdr = (struct rsn_ie_hdr *) buf;
|
||||||
|
hdr->elem_id = WLAN_EID_RSN;
|
||||||
|
WPA_PUT_LE16(hdr->version, RSN_VERSION);
|
||||||
|
pos = (u8 *) (hdr + 1);
|
||||||
|
|
||||||
|
pos = rsne_write_data(buf, len, pos, conf->wpa_group,
|
||||||
|
conf->rsn_pairwise, conf->wpa_key_mgmt,
|
||||||
|
wpa_own_rsn_capab(conf, conf->ieee80211w), pmkid,
|
||||||
|
conf->ieee80211w, conf->group_mgmt_cipher);
|
||||||
|
if (!pos)
|
||||||
|
return -1;
|
||||||
|
|
||||||
hdr->len = (pos - buf) - 2;
|
hdr->len = (pos - buf) - 2;
|
||||||
|
|
||||||
|
@ -406,16 +424,74 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
static int wpa_write_rsne_override(struct wpa_auth_config *conf, u8 *buf,
|
||||||
|
size_t len)
|
||||||
{
|
{
|
||||||
u8 *pos = buf;
|
u8 *pos, *len_pos;
|
||||||
u32 capab = 0, tmp;
|
|
||||||
size_t flen;
|
|
||||||
|
|
||||||
if (wpa_key_mgmt_sae(conf->wpa_key_mgmt) &&
|
pos = buf;
|
||||||
|
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||||
|
len_pos = pos++;
|
||||||
|
|
||||||
|
WPA_PUT_BE32(pos, RSNE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
pos += 4;
|
||||||
|
|
||||||
|
WPA_PUT_LE16(pos, RSN_VERSION);
|
||||||
|
pos += 2;
|
||||||
|
|
||||||
|
pos = rsne_write_data(buf, len, pos, conf->wpa_group,
|
||||||
|
conf->rsn_override_pairwise,
|
||||||
|
conf->rsn_override_key_mgmt,
|
||||||
|
wpa_own_rsn_capab(conf, conf->rsn_override_mfp),
|
||||||
|
NULL, conf->rsn_override_mfp,
|
||||||
|
conf->group_mgmt_cipher);
|
||||||
|
if (!pos)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*len_pos = (pos - buf) - 2;
|
||||||
|
|
||||||
|
return pos - buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_write_rsne_override_2(struct wpa_auth_config *conf, u8 *buf,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
u8 *pos, *len_pos;
|
||||||
|
|
||||||
|
pos = buf;
|
||||||
|
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||||
|
len_pos = pos++;
|
||||||
|
|
||||||
|
WPA_PUT_BE32(pos, RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
|
||||||
|
pos += 4;
|
||||||
|
|
||||||
|
WPA_PUT_LE16(pos, RSN_VERSION);
|
||||||
|
pos += 2;
|
||||||
|
|
||||||
|
pos = rsne_write_data(buf, len, pos, conf->wpa_group,
|
||||||
|
conf->rsn_override_pairwise_2,
|
||||||
|
conf->rsn_override_key_mgmt_2,
|
||||||
|
wpa_own_rsn_capab(conf, conf->rsn_override_mfp_2),
|
||||||
|
NULL, conf->rsn_override_mfp_2,
|
||||||
|
conf->group_mgmt_cipher);
|
||||||
|
if (!pos)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*len_pos = (pos - buf) - 2;
|
||||||
|
|
||||||
|
return pos - buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static u32 rsnxe_capab(struct wpa_auth_config *conf, int key_mgmt)
|
||||||
|
{
|
||||||
|
u32 capab = 0;
|
||||||
|
|
||||||
|
if (wpa_key_mgmt_sae(key_mgmt) &&
|
||||||
(conf->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
|
(conf->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
|
||||||
conf->sae_pwe == SAE_PWE_BOTH || conf->sae_pk ||
|
conf->sae_pwe == SAE_PWE_BOTH || conf->sae_pk ||
|
||||||
wpa_key_mgmt_sae_ext_key(conf->wpa_key_mgmt))) {
|
wpa_key_mgmt_sae_ext_key(key_mgmt))) {
|
||||||
capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
|
capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
|
||||||
#ifdef CONFIG_SAE_PK
|
#ifdef CONFIG_SAE_PK
|
||||||
if (conf->sae_pk)
|
if (conf->sae_pk)
|
||||||
|
@ -432,6 +508,18 @@ int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
||||||
if (conf->ssid_protection)
|
if (conf->ssid_protection)
|
||||||
capab |= BIT(WLAN_RSNX_CAPAB_SSID_PROTECTION);
|
capab |= BIT(WLAN_RSNX_CAPAB_SSID_PROTECTION);
|
||||||
|
|
||||||
|
return capab;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
||||||
|
{
|
||||||
|
u8 *pos = buf;
|
||||||
|
u32 capab = 0, tmp;
|
||||||
|
size_t flen;
|
||||||
|
|
||||||
|
capab = rsnxe_capab(conf, conf->wpa_key_mgmt);
|
||||||
|
|
||||||
if (!capab)
|
if (!capab)
|
||||||
return 0; /* no supported extended RSN capabilities */
|
return 0; /* no supported extended RSN capabilities */
|
||||||
tmp = capab;
|
tmp = capab;
|
||||||
|
@ -455,6 +543,37 @@ int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_write_rsnxe_override(struct wpa_auth_config *conf, u8 *buf,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
u8 *pos = buf;
|
||||||
|
u16 capab;
|
||||||
|
size_t flen;
|
||||||
|
|
||||||
|
capab = rsnxe_capab(conf, conf->rsn_override_key_mgmt |
|
||||||
|
conf->rsn_override_key_mgmt_2);
|
||||||
|
|
||||||
|
flen = (capab & 0xff00) ? 2 : 1;
|
||||||
|
if (!capab)
|
||||||
|
return 0; /* no supported extended RSN capabilities */
|
||||||
|
if (len < 2 + flen)
|
||||||
|
return -1;
|
||||||
|
capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */
|
||||||
|
|
||||||
|
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||||
|
*pos++ = 4 + flen;
|
||||||
|
WPA_PUT_BE32(pos, RSNXE_OVERRIDE_IE_VENDOR_TYPE);
|
||||||
|
pos += 4;
|
||||||
|
|
||||||
|
*pos++ = capab & 0x00ff;
|
||||||
|
capab >>= 8;
|
||||||
|
if (capab)
|
||||||
|
*pos++ = capab;
|
||||||
|
|
||||||
|
return pos - buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static u8 * wpa_write_osen(struct wpa_auth_config *conf, u8 *eid)
|
static u8 * wpa_write_osen(struct wpa_auth_config *conf, u8 *eid)
|
||||||
{
|
{
|
||||||
u8 *len;
|
u8 *len;
|
||||||
|
@ -508,7 +627,7 @@ static u8 * wpa_write_osen(struct wpa_auth_config *conf, u8 *eid)
|
||||||
|
|
||||||
int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
|
int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
|
||||||
{
|
{
|
||||||
u8 *pos, buf[128];
|
u8 *pos, buf[256];
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
@ -561,6 +680,31 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
|
||||||
return res;
|
return res;
|
||||||
pos += res;
|
pos += res;
|
||||||
}
|
}
|
||||||
|
if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
|
||||||
|
wpa_auth->conf.rsn_override_key_mgmt) {
|
||||||
|
res = wpa_write_rsne_override(&wpa_auth->conf,
|
||||||
|
pos, buf + sizeof(buf) - pos);
|
||||||
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
pos += res;
|
||||||
|
}
|
||||||
|
if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
|
||||||
|
wpa_auth->conf.rsn_override_key_mgmt_2) {
|
||||||
|
res = wpa_write_rsne_override_2(&wpa_auth->conf, pos,
|
||||||
|
buf + sizeof(buf) - pos);
|
||||||
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
pos += res;
|
||||||
|
}
|
||||||
|
if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
|
||||||
|
(wpa_auth->conf.rsn_override_key_mgmt ||
|
||||||
|
wpa_auth->conf.rsn_override_key_mgmt_2)) {
|
||||||
|
res = wpa_write_rsnxe_override(&wpa_auth->conf, pos,
|
||||||
|
buf + sizeof(buf) - pos);
|
||||||
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
pos += res;
|
||||||
|
}
|
||||||
|
|
||||||
os_free(wpa_auth->wpa_ie);
|
os_free(wpa_auth->wpa_ie);
|
||||||
wpa_auth->wpa_ie = os_malloc(pos - buf);
|
wpa_auth->wpa_ie = os_malloc(pos - buf);
|
||||||
|
@ -569,6 +713,59 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
|
||||||
os_memcpy(wpa_auth->wpa_ie, buf, pos - buf);
|
os_memcpy(wpa_auth->wpa_ie, buf, pos - buf);
|
||||||
wpa_auth->wpa_ie_len = pos - buf;
|
wpa_auth->wpa_ie_len = pos - buf;
|
||||||
|
|
||||||
|
if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
|
||||||
|
wpa_auth->conf.rsn_override_key_mgmt) {
|
||||||
|
res = wpa_write_rsne_override(&wpa_auth->conf, buf,
|
||||||
|
sizeof(buf));
|
||||||
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
os_free(wpa_auth->rsne_override);
|
||||||
|
wpa_auth->rsne_override = os_malloc(res - 4);
|
||||||
|
if (!wpa_auth->rsne_override)
|
||||||
|
return -1;
|
||||||
|
pos = wpa_auth->rsne_override;
|
||||||
|
*pos++ = WLAN_EID_RSN;
|
||||||
|
*pos++ = res - 2 - 4;
|
||||||
|
os_memcpy(pos, &buf[2 + 4], res - 2 - 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
|
||||||
|
wpa_auth->conf.rsn_override_key_mgmt_2) {
|
||||||
|
res = wpa_write_rsne_override_2(&wpa_auth->conf, buf,
|
||||||
|
sizeof(buf));
|
||||||
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
os_free(wpa_auth->rsne_override_2);
|
||||||
|
wpa_auth->rsne_override_2 = os_malloc(res - 4);
|
||||||
|
if (!wpa_auth->rsne_override_2)
|
||||||
|
return -1;
|
||||||
|
pos = wpa_auth->rsne_override_2;
|
||||||
|
*pos++ = WLAN_EID_RSN;
|
||||||
|
*pos++ = res - 2 - 4;
|
||||||
|
os_memcpy(pos, &buf[2 + 4], res - 2 - 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
|
||||||
|
(wpa_auth->conf.rsn_override_key_mgmt ||
|
||||||
|
wpa_auth->conf.rsn_override_key_mgmt_2)) {
|
||||||
|
res = wpa_write_rsnxe_override(&wpa_auth->conf, buf,
|
||||||
|
sizeof(buf));
|
||||||
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
os_free(wpa_auth->rsnxe_override);
|
||||||
|
if (res == 0) {
|
||||||
|
wpa_auth->rsnxe_override = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
wpa_auth->rsnxe_override = os_malloc(res - 4);
|
||||||
|
if (!wpa_auth->rsnxe_override)
|
||||||
|
return -1;
|
||||||
|
pos = wpa_auth->rsnxe_override;
|
||||||
|
*pos++ = WLAN_EID_RSNX;
|
||||||
|
*pos++ = res - 2 - 4;
|
||||||
|
os_memcpy(pos, &buf[2 + 4], res - 2 - 4);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,7 +970,9 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||||
return WPA_INVALID_GROUP;
|
return WPA_INVALID_GROUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt;
|
key_mgmt = data.key_mgmt & (wpa_auth->conf.wpa_key_mgmt |
|
||||||
|
wpa_auth->conf.rsn_override_key_mgmt |
|
||||||
|
wpa_auth->conf.rsn_override_key_mgmt_2);
|
||||||
if (!key_mgmt) {
|
if (!key_mgmt) {
|
||||||
wpa_printf(MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from "
|
wpa_printf(MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from "
|
||||||
MACSTR, data.key_mgmt, MAC2STR(sm->addr));
|
MACSTR, data.key_mgmt, MAC2STR(sm->addr));
|
||||||
|
@ -843,7 +1042,10 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
|
sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
|
||||||
|
|
||||||
if (version == WPA_PROTO_RSN)
|
if (version == WPA_PROTO_RSN)
|
||||||
ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_pairwise;
|
ciphers = data.pairwise_cipher &
|
||||||
|
(wpa_auth->conf.rsn_pairwise |
|
||||||
|
wpa_auth->conf.rsn_override_pairwise |
|
||||||
|
wpa_auth->conf.rsn_override_pairwise_2);
|
||||||
else
|
else
|
||||||
ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise;
|
ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise;
|
||||||
if (!ciphers) {
|
if (!ciphers) {
|
||||||
|
@ -1229,7 +1431,7 @@ bool wpa_auth_write_fd_rsn_info(struct wpa_authenticator *wpa_auth,
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* RSN Capability (B0..B15) */
|
/* RSN Capability (B0..B15) */
|
||||||
WPA_PUT_LE16(pos, wpa_own_rsn_capab(conf));
|
WPA_PUT_LE16(pos, wpa_own_rsn_capab(conf, conf->ieee80211w));
|
||||||
pos += 2;
|
pos += 2;
|
||||||
|
|
||||||
/* Group Data Cipher Suite Selector (B16..B21) */
|
/* Group Data Cipher Suite Selector (B16..B21) */
|
||||||
|
|
Loading…
Reference in a new issue