nl80211: Allow up to 64-byte PMK in NL80211_CMD_SET_PMKSA

Kernel commit 22e76844c566 - ("ieee80211: Increase PMK maximum length to
 64 bytes") increased the maximum allowed length for NL80211_ATTR_PMK to
64 bytes. Thus, allow sending 64 bytes PMK in NL80211_CMD_SET_PMKSA and
if NL80211_CMD_SET_PMKSA fails with ERANGE try NL80211_CMD_SET_PMKSA
again without PMK. Also, skip sending PMK when PMK length is greater
than 64 bytes.

This is needed for some newer cases like DPP with NIST P-521 and
SAE-EXT-KEY with group 21. The kernel change from 48 to 64 octets is
from February 2018, so the new limit should be available in most cases
that might want to use these new mechanisms. Maintain a backwards
compatible fallback option for now to cover some earlier needs for DPP.

Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
This commit is contained in:
Veerendranath Jakkam 2022-11-08 18:41:41 +05:30 committed by Jouni Malinen
parent 1e0b7379d6
commit 15583802b9

View file

@ -9104,10 +9104,14 @@ static const char * nl80211_get_radio_name(void *priv)
static int nl80211_pmkid(struct i802_bss *bss, int cmd,
struct wpa_pmkid_params *params)
struct wpa_pmkid_params *params, bool skip_pmk)
{
struct nl_msg *msg;
const size_t PMK_MAX_LEN = 48; /* current cfg80211 limit */
if (cmd == NL80211_CMD_SET_PMKSA)
wpa_printf(MSG_DEBUG,
"nl80211: NL80211_CMD_SET_PMKSA with skip_pmk=%s pmk_len=%zu",
skip_pmk ? "true" : "false", params->pmk_len);
if (!(msg = nl80211_bss_msg(bss, 0, cmd)) ||
(params->pmkid &&
@ -9126,7 +9130,7 @@ static int nl80211_pmkid(struct i802_bss *bss, int cmd,
nla_put_u8(msg, NL80211_ATTR_PMK_REAUTH_THRESHOLD,
params->pmk_reauth_threshold)) ||
(cmd != NL80211_CMD_DEL_PMKSA &&
params->pmk_len && params->pmk_len <= PMK_MAX_LEN &&
params->pmk_len && !skip_pmk &&
nla_put(msg, NL80211_ATTR_PMK, params->pmk_len, params->pmk))) {
nl80211_nlmsg_clear(msg);
nlmsg_free(msg);
@ -9140,6 +9144,9 @@ static int nl80211_pmkid(struct i802_bss *bss, int cmd,
static int nl80211_add_pmkid(void *priv, struct wpa_pmkid_params *params)
{
struct i802_bss *bss = priv;
const size_t PMK_MAX_LEN = 64; /* current cfg80211 limit */
const size_t LEGACY_PMK_MAX_LEN = 48; /* old cfg80211 limit */
bool skip_pmk = params->pmk_len > PMK_MAX_LEN;
int ret;
if (params->bssid)
@ -9152,7 +9159,15 @@ static int nl80211_add_pmkid(void *priv, struct wpa_pmkid_params *params)
wpa_ssid_txt(params->ssid, params->ssid_len));
}
ret = nl80211_pmkid(bss, NL80211_CMD_SET_PMKSA, params);
ret = nl80211_pmkid(bss, NL80211_CMD_SET_PMKSA, params, skip_pmk);
/*
* Try again by skipping PMK if the first attempt failed with ERANGE
* error, PMK was not skipped, and PMK length is greater than the
* legacy kernel maximum allowed limit.
*/
if (ret == -ERANGE && !skip_pmk &&
params->pmk_len > LEGACY_PMK_MAX_LEN)
ret = nl80211_pmkid(bss, NL80211_CMD_SET_PMKSA, params, true);
if (ret < 0) {
wpa_printf(MSG_DEBUG,
"nl80211: NL80211_CMD_SET_PMKSA failed: %d (%s)",
@ -9178,7 +9193,7 @@ static int nl80211_remove_pmkid(void *priv, struct wpa_pmkid_params *params)
wpa_ssid_txt(params->ssid, params->ssid_len));
}
ret = nl80211_pmkid(bss, NL80211_CMD_DEL_PMKSA, params);
ret = nl80211_pmkid(bss, NL80211_CMD_DEL_PMKSA, params, true);
if (ret < 0) {
wpa_printf(MSG_DEBUG,
"nl80211: NL80211_CMD_DEL_PMKSA failed: %d (%s)",