Add group_mgmt network parameter for PMF cipher selection
The new wpa_supplicant network parameter group_mgmt can be used to specify which group management ciphers (AES-128-CMAC, BIP-GMAC-128, BIP-GMAC-256, BIP-CMAC-256) are allowed for the network. If not specified, the current behavior is maintained (i.e., follow what the AP advertises). The parameter can list multiple space separate ciphers. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
0ad5893a2f
commit
61a56c1480
11 changed files with 150 additions and 6 deletions
|
@ -2072,6 +2072,14 @@ int wpa_parse_cipher(const char *value)
|
||||||
val |= WPA_CIPHER_NONE;
|
val |= WPA_CIPHER_NONE;
|
||||||
else if (os_strcmp(start, "GTK_NOT_USED") == 0)
|
else if (os_strcmp(start, "GTK_NOT_USED") == 0)
|
||||||
val |= WPA_CIPHER_GTK_NOT_USED;
|
val |= WPA_CIPHER_GTK_NOT_USED;
|
||||||
|
else if (os_strcmp(start, "AES-128-CMAC") == 0)
|
||||||
|
val |= WPA_CIPHER_AES_128_CMAC;
|
||||||
|
else if (os_strcmp(start, "BIP-GMAC-128") == 0)
|
||||||
|
val |= WPA_CIPHER_BIP_GMAC_128;
|
||||||
|
else if (os_strcmp(start, "BIP-GMAC-256") == 0)
|
||||||
|
val |= WPA_CIPHER_BIP_GMAC_256;
|
||||||
|
else if (os_strcmp(start, "BIP-CMAC-256") == 0)
|
||||||
|
val |= WPA_CIPHER_BIP_CMAC_256;
|
||||||
else {
|
else {
|
||||||
os_free(buf);
|
os_free(buf);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -2127,6 +2135,34 @@ int wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim)
|
||||||
return -1;
|
return -1;
|
||||||
pos += ret;
|
pos += ret;
|
||||||
}
|
}
|
||||||
|
if (ciphers & WPA_CIPHER_AES_128_CMAC) {
|
||||||
|
ret = os_snprintf(pos, end - pos, "%sAES-128-CMAC",
|
||||||
|
pos == start ? "" : delim);
|
||||||
|
if (os_snprintf_error(end - pos, ret))
|
||||||
|
return -1;
|
||||||
|
pos += ret;
|
||||||
|
}
|
||||||
|
if (ciphers & WPA_CIPHER_BIP_GMAC_128) {
|
||||||
|
ret = os_snprintf(pos, end - pos, "%sBIP-GMAC-128",
|
||||||
|
pos == start ? "" : delim);
|
||||||
|
if (os_snprintf_error(end - pos, ret))
|
||||||
|
return -1;
|
||||||
|
pos += ret;
|
||||||
|
}
|
||||||
|
if (ciphers & WPA_CIPHER_BIP_GMAC_256) {
|
||||||
|
ret = os_snprintf(pos, end - pos, "%sBIP-GMAC-256",
|
||||||
|
pos == start ? "" : delim);
|
||||||
|
if (os_snprintf_error(end - pos, ret))
|
||||||
|
return -1;
|
||||||
|
pos += ret;
|
||||||
|
}
|
||||||
|
if (ciphers & WPA_CIPHER_BIP_CMAC_256) {
|
||||||
|
ret = os_snprintf(pos, end - pos, "%sBIP-CMAC-256",
|
||||||
|
pos == start ? "" : delim);
|
||||||
|
if (os_snprintf_error(end - pos, ret))
|
||||||
|
return -1;
|
||||||
|
pos += ret;
|
||||||
|
}
|
||||||
if (ciphers & WPA_CIPHER_NONE) {
|
if (ciphers & WPA_CIPHER_NONE) {
|
||||||
ret = os_snprintf(pos, end - pos, "%sNONE",
|
ret = os_snprintf(pos, end - pos, "%sNONE",
|
||||||
pos == start ? "" : delim);
|
pos == start ? "" : delim);
|
||||||
|
|
|
@ -29,6 +29,9 @@ WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256)
|
||||||
(WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_TKIP | \
|
(WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_TKIP | \
|
||||||
WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256 | \
|
WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256 | \
|
||||||
WPA_CIPHER_GTK_NOT_USED)
|
WPA_CIPHER_GTK_NOT_USED)
|
||||||
|
#define WPA_ALLOWED_GROUP_MGMT_CIPHERS \
|
||||||
|
(WPA_CIPHER_AES_128_CMAC | WPA_CIPHER_BIP_GMAC_128 | WPA_CIPHER_BIP_GMAC_256 | \
|
||||||
|
WPA_CIPHER_BIP_CMAC_256)
|
||||||
|
|
||||||
#define WPA_SELECTOR_LEN 4
|
#define WPA_SELECTOR_LEN 4
|
||||||
#define WPA_VERSION 1
|
#define WPA_VERSION 1
|
||||||
|
|
|
@ -814,7 +814,7 @@ struct wpa_driver_associate_params {
|
||||||
* WPA information element to be included in (Re)Association
|
* WPA information element to be included in (Re)Association
|
||||||
* Request (including information element id and length). Use
|
* Request (including information element id and length). Use
|
||||||
* of this WPA IE is optional. If the driver generates the WPA
|
* of this WPA IE is optional. If the driver generates the WPA
|
||||||
* IE, it can use pairwise_suite, group_suite, and
|
* IE, it can use pairwise_suite, group_suite, group_mgmt_suite, and
|
||||||
* key_mgmt_suite to select proper algorithms. In this case,
|
* key_mgmt_suite to select proper algorithms. In this case,
|
||||||
* the driver has to notify wpa_supplicant about the used WPA
|
* the driver has to notify wpa_supplicant about the used WPA
|
||||||
* IE by generating an event that the interface code will
|
* IE by generating an event that the interface code will
|
||||||
|
@ -853,6 +853,13 @@ struct wpa_driver_associate_params {
|
||||||
*/
|
*/
|
||||||
unsigned int group_suite;
|
unsigned int group_suite;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mgmt_group_suite - Selected group management cipher suite (WPA_CIPHER_*)
|
||||||
|
*
|
||||||
|
* This is usually ignored if @wpa_ie is used.
|
||||||
|
*/
|
||||||
|
unsigned int mgmt_group_suite;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* key_mgmt_suite - Selected key management suite (WPA_KEY_MGMT_*)
|
* key_mgmt_suite - Selected key management suite (WPA_KEY_MGMT_*)
|
||||||
*
|
*
|
||||||
|
|
|
@ -1027,7 +1027,8 @@ class WpaSupplicant:
|
||||||
"bssid_whitelist", "mem_only_psk", "eap_workaround",
|
"bssid_whitelist", "mem_only_psk", "eap_workaround",
|
||||||
"engine", "fils_dh_group", "bssid_hint",
|
"engine", "fils_dh_group", "bssid_hint",
|
||||||
"dpp_csign", "dpp_csign_expiry",
|
"dpp_csign", "dpp_csign_expiry",
|
||||||
"dpp_netaccesskey", "dpp_netaccesskey_expiry" ]
|
"dpp_netaccesskey", "dpp_netaccesskey_expiry",
|
||||||
|
"group_mgmt" ]
|
||||||
for field in not_quoted:
|
for field in not_quoted:
|
||||||
if field in kwargs and kwargs[field]:
|
if field in kwargs and kwargs[field]:
|
||||||
self.set_network(id, field, kwargs[field])
|
self.set_network(id, field, kwargs[field])
|
||||||
|
|
|
@ -1148,6 +1148,40 @@ static char * wpa_config_write_group(const struct parse_data *data,
|
||||||
#endif /* NO_CONFIG_WRITE */
|
#endif /* NO_CONFIG_WRITE */
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_config_parse_group_mgmt(const struct parse_data *data,
|
||||||
|
struct wpa_ssid *ssid, int line,
|
||||||
|
const char *value)
|
||||||
|
{
|
||||||
|
int val;
|
||||||
|
|
||||||
|
val = wpa_config_parse_cipher(line, value);
|
||||||
|
if (val == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (val & ~WPA_ALLOWED_GROUP_MGMT_CIPHERS) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"Line %d: not allowed group management cipher (0x%x).",
|
||||||
|
line, val);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ssid->group_mgmt_cipher == val)
|
||||||
|
return 1;
|
||||||
|
wpa_printf(MSG_MSGDUMP, "group_mgmt: 0x%x", val);
|
||||||
|
ssid->group_mgmt_cipher = val;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef NO_CONFIG_WRITE
|
||||||
|
static char * wpa_config_write_group_mgmt(const struct parse_data *data,
|
||||||
|
struct wpa_ssid *ssid)
|
||||||
|
{
|
||||||
|
return wpa_config_write_cipher(ssid->group_mgmt_cipher);
|
||||||
|
}
|
||||||
|
#endif /* NO_CONFIG_WRITE */
|
||||||
|
|
||||||
|
|
||||||
static int wpa_config_parse_auth_alg(const struct parse_data *data,
|
static int wpa_config_parse_auth_alg(const struct parse_data *data,
|
||||||
struct wpa_ssid *ssid, int line,
|
struct wpa_ssid *ssid, int line,
|
||||||
const char *value)
|
const char *value)
|
||||||
|
@ -2086,6 +2120,7 @@ static const struct parse_data ssid_fields[] = {
|
||||||
{ INT(bg_scan_period) },
|
{ INT(bg_scan_period) },
|
||||||
{ FUNC(pairwise) },
|
{ FUNC(pairwise) },
|
||||||
{ FUNC(group) },
|
{ FUNC(group) },
|
||||||
|
{ FUNC(group_mgmt) },
|
||||||
{ FUNC(auth_alg) },
|
{ FUNC(auth_alg) },
|
||||||
{ FUNC(scan_freq) },
|
{ FUNC(scan_freq) },
|
||||||
{ FUNC(freq_list) },
|
{ FUNC(freq_list) },
|
||||||
|
|
|
@ -593,6 +593,22 @@ static void write_group(FILE *f, struct wpa_ssid *ssid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void write_group_mgmt(FILE *f, struct wpa_ssid *ssid)
|
||||||
|
{
|
||||||
|
char *value;
|
||||||
|
|
||||||
|
if (!ssid->group_mgmt_cipher)
|
||||||
|
return;
|
||||||
|
|
||||||
|
value = wpa_config_get(ssid, "group_mgmt");
|
||||||
|
if (!value)
|
||||||
|
return;
|
||||||
|
if (value[0])
|
||||||
|
fprintf(f, "\tgroup_mgmt=%s\n", value);
|
||||||
|
os_free(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void write_auth_alg(FILE *f, struct wpa_ssid *ssid)
|
static void write_auth_alg(FILE *f, struct wpa_ssid *ssid)
|
||||||
{
|
{
|
||||||
char *value;
|
char *value;
|
||||||
|
@ -734,6 +750,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
|
||||||
INT_DEF(bg_scan_period, DEFAULT_BG_SCAN_PERIOD);
|
INT_DEF(bg_scan_period, DEFAULT_BG_SCAN_PERIOD);
|
||||||
write_pairwise(f, ssid);
|
write_pairwise(f, ssid);
|
||||||
write_group(f, ssid);
|
write_group(f, ssid);
|
||||||
|
write_group_mgmt(f, ssid);
|
||||||
write_auth_alg(f, ssid);
|
write_auth_alg(f, ssid);
|
||||||
STR(bgscan);
|
STR(bgscan);
|
||||||
STR(autoscan);
|
STR(autoscan);
|
||||||
|
|
|
@ -209,6 +209,15 @@ struct wpa_ssid {
|
||||||
*/
|
*/
|
||||||
int group_cipher;
|
int group_cipher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* group_mgmt_cipher - Bitfield of allowed group management ciphers
|
||||||
|
*
|
||||||
|
* This is a bitfield of WPA_CIPHER_AES_128_CMAC and WPA_CIPHER_BIP_*
|
||||||
|
* values. If 0, no constraint is used for the cipher, i.e., whatever
|
||||||
|
* the AP uses is accepted.
|
||||||
|
*/
|
||||||
|
int group_mgmt_cipher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* key_mgmt - Bitfield of allowed key management protocols
|
* key_mgmt - Bitfield of allowed key management protocols
|
||||||
*
|
*
|
||||||
|
|
|
@ -565,6 +565,14 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ssid->group_mgmt_cipher &&
|
||||||
|
!(ie.mgmt_group_cipher & ssid->group_mgmt_cipher)) {
|
||||||
|
if (debug_print)
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG,
|
||||||
|
" skip RSN IE - group mgmt cipher mismatch");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(ie.key_mgmt & ssid->key_mgmt)) {
|
if (!(ie.key_mgmt & ssid->key_mgmt)) {
|
||||||
if (debug_print)
|
if (debug_print)
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG,
|
wpa_dbg(wpa_s, MSG_DEBUG,
|
||||||
|
|
|
@ -1227,6 +1227,7 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
|
||||||
params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
|
params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
|
||||||
params.pairwise_suite = wpa_s->pairwise_cipher;
|
params.pairwise_suite = wpa_s->pairwise_cipher;
|
||||||
params.group_suite = wpa_s->group_cipher;
|
params.group_suite = wpa_s->group_cipher;
|
||||||
|
params.mgmt_group_suite = wpa_s->mgmt_group_cipher;
|
||||||
params.key_mgmt_suite = wpa_s->key_mgmt;
|
params.key_mgmt_suite = wpa_s->key_mgmt;
|
||||||
params.wpa_proto = wpa_s->wpa_proto;
|
params.wpa_proto = wpa_s->wpa_proto;
|
||||||
#ifdef CONFIG_HT_OVERRIDES
|
#ifdef CONFIG_HT_OVERRIDES
|
||||||
|
|
|
@ -1232,9 +1232,24 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
|
||||||
ie.pairwise_cipher = ssid->pairwise_cipher;
|
ie.pairwise_cipher = ssid->pairwise_cipher;
|
||||||
ie.key_mgmt = ssid->key_mgmt;
|
ie.key_mgmt = ssid->key_mgmt;
|
||||||
#ifdef CONFIG_IEEE80211W
|
#ifdef CONFIG_IEEE80211W
|
||||||
ie.mgmt_group_cipher =
|
ie.mgmt_group_cipher = 0;
|
||||||
ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
|
if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
|
||||||
WPA_CIPHER_AES_128_CMAC : 0;
|
if (ssid->group_mgmt_cipher &
|
||||||
|
WPA_CIPHER_BIP_GMAC_256)
|
||||||
|
ie.mgmt_group_cipher =
|
||||||
|
WPA_CIPHER_BIP_GMAC_256;
|
||||||
|
else if (ssid->group_mgmt_cipher &
|
||||||
|
WPA_CIPHER_BIP_CMAC_256)
|
||||||
|
ie.mgmt_group_cipher =
|
||||||
|
WPA_CIPHER_BIP_CMAC_256;
|
||||||
|
else if (ssid->group_mgmt_cipher &
|
||||||
|
WPA_CIPHER_BIP_GMAC_128)
|
||||||
|
ie.mgmt_group_cipher =
|
||||||
|
WPA_CIPHER_BIP_GMAC_128;
|
||||||
|
else
|
||||||
|
ie.mgmt_group_cipher =
|
||||||
|
WPA_CIPHER_AES_128_CMAC;
|
||||||
|
}
|
||||||
#endif /* CONFIG_IEEE80211W */
|
#endif /* CONFIG_IEEE80211W */
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
|
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
|
||||||
"based on configuration");
|
"based on configuration");
|
||||||
|
@ -1387,6 +1402,8 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211W
|
#ifdef CONFIG_IEEE80211W
|
||||||
sel = ie.mgmt_group_cipher;
|
sel = ie.mgmt_group_cipher;
|
||||||
|
if (ssid->group_mgmt_cipher)
|
||||||
|
sel &= ssid->group_mgmt_cipher;
|
||||||
if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
|
if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
|
||||||
!(ie.capabilities & WPA_CAPABILITY_MFPC))
|
!(ie.capabilities & WPA_CAPABILITY_MFPC))
|
||||||
sel = 0;
|
sel = 0;
|
||||||
|
@ -2301,7 +2318,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
|
||||||
size_t wpa_ie_len;
|
size_t wpa_ie_len;
|
||||||
int use_crypt, ret, i, bssid_changed;
|
int use_crypt, ret, i, bssid_changed;
|
||||||
int algs = WPA_AUTH_ALG_OPEN;
|
int algs = WPA_AUTH_ALG_OPEN;
|
||||||
unsigned int cipher_pairwise, cipher_group;
|
unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt;
|
||||||
struct wpa_driver_associate_params params;
|
struct wpa_driver_associate_params params;
|
||||||
int wep_keys_set = 0;
|
int wep_keys_set = 0;
|
||||||
int assoc_failed = 0;
|
int assoc_failed = 0;
|
||||||
|
@ -2665,6 +2682,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
|
||||||
use_crypt = 1;
|
use_crypt = 1;
|
||||||
cipher_pairwise = wpa_s->pairwise_cipher;
|
cipher_pairwise = wpa_s->pairwise_cipher;
|
||||||
cipher_group = wpa_s->group_cipher;
|
cipher_group = wpa_s->group_cipher;
|
||||||
|
cipher_group_mgmt = wpa_s->mgmt_group_cipher;
|
||||||
if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
|
if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
|
||||||
wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
|
wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
|
||||||
if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
|
if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
|
||||||
|
@ -2748,6 +2766,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
|
||||||
params.wpa_ie_len = wpa_ie_len;
|
params.wpa_ie_len = wpa_ie_len;
|
||||||
params.pairwise_suite = cipher_pairwise;
|
params.pairwise_suite = cipher_pairwise;
|
||||||
params.group_suite = cipher_group;
|
params.group_suite = cipher_group;
|
||||||
|
params.mgmt_group_suite = cipher_group_mgmt;
|
||||||
params.key_mgmt_suite = wpa_s->key_mgmt;
|
params.key_mgmt_suite = wpa_s->key_mgmt;
|
||||||
params.wpa_proto = wpa_s->wpa_proto;
|
params.wpa_proto = wpa_s->wpa_proto;
|
||||||
params.auth_alg = algs;
|
params.auth_alg = algs;
|
||||||
|
|
|
@ -879,6 +879,14 @@ fast_reauth=1
|
||||||
# WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key [IEEE 802.11]
|
# WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key [IEEE 802.11]
|
||||||
# If not set, this defaults to: CCMP TKIP WEP104 WEP40
|
# If not set, this defaults to: CCMP TKIP WEP104 WEP40
|
||||||
#
|
#
|
||||||
|
# group_mgmt: list of accepted group management ciphers for RSN (PMF)
|
||||||
|
# AES-128-CMAC = BIP-CMAC-128
|
||||||
|
# BIP-GMAC-128
|
||||||
|
# BIP-GMAC-256
|
||||||
|
# BIP-CMAC-256
|
||||||
|
# If not set, no constraint on the cipher, i.e., accept whichever cipher the AP
|
||||||
|
# indicates.
|
||||||
|
#
|
||||||
# psk: WPA preshared key; 256-bit pre-shared key
|
# psk: WPA preshared key; 256-bit pre-shared key
|
||||||
# The key used in WPA-PSK mode can be entered either as 64 hex-digits, i.e.,
|
# The key used in WPA-PSK mode can be entered either as 64 hex-digits, i.e.,
|
||||||
# 32 bytes or as an ASCII passphrase (in which case, the real PSK will be
|
# 32 bytes or as an ASCII passphrase (in which case, the real PSK will be
|
||||||
|
|
Loading…
Reference in a new issue