staging: rtl8723bs: Fix key-store index handling
authorHans de Goede <hdegoede@redhat.com>
Mon, 6 Mar 2023 15:35:11 +0000 (16:35 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 8 Mar 2023 16:58:44 +0000 (17:58 +0100)
There are 2 issues with the key-store index handling

1. The non WEP key stores can store keys with indexes 0 - BIP_MAX_KEYID,
   this means that they should be an array with BIP_MAX_KEYID + 1
   entries. But some of the arrays where just BIP_MAX_KEYID entries
   big. While one other array was hardcoded to a size of 6 entries,
   instead of using the BIP_MAX_KEYID define.

2. The rtw_cfg80211_set_encryption() and wpa_set_encryption() functions
   index check where checking that the passed in key-index would fit
   inside both the WEP key store (which only has 4 entries) as well as
   in the non WEP key stores. This breaks any attempts to set non WEP
   keys with index 4 or 5.

Issue 2. specifically breaks wifi connection with some access points
which advertise PMF support. Without this fix connecting to these
access points fails with the following wpa_supplicant messages:

 nl80211: kernel reports: key addition failed
 wlan0: WPA: Failed to configure IGTK to the driver
 wlan0: RSN: Failed to configure IGTK
 wlan0: CTRL-EVENT-DISCONNECTED bssid=... reason=1 locally_generated=1

Fix 1. by using the right size for the key-stores. After this 2. can
safely be fixed by checking the right max-index value depending on the
used algorithm, fixing wifi not working with some PMF capable APs.

Cc: stable@vger.kernel.org
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20230306153512.162104-1-hdegoede@redhat.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/rtl8723bs/include/rtw_security.h
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
drivers/staging/rtl8723bs/os_dep/ioctl_linux.c

index a68b738..7587fa8 100644 (file)
@@ -107,13 +107,13 @@ struct security_priv {
 
        u32 dot118021XGrpPrivacy;       /*  This specify the privacy algthm. used for Grp key */
        u32 dot118021XGrpKeyid;         /*  key id used for Grp Key (tx key index) */
-       union Keytype   dot118021XGrpKey[BIP_MAX_KEYID];        /*  802.1x Group Key, for inx0 and inx1 */
-       union Keytype   dot118021XGrptxmickey[BIP_MAX_KEYID];
-       union Keytype   dot118021XGrprxmickey[BIP_MAX_KEYID];
+       union Keytype   dot118021XGrpKey[BIP_MAX_KEYID + 1];    /*  802.1x Group Key, for inx0 and inx1 */
+       union Keytype   dot118021XGrptxmickey[BIP_MAX_KEYID + 1];
+       union Keytype   dot118021XGrprxmickey[BIP_MAX_KEYID + 1];
        union pn48              dot11Grptxpn;                   /*  PN48 used for Grp Key xmit. */
        union pn48              dot11Grprxpn;                   /*  PN48 used for Grp Key recv. */
        u32 dot11wBIPKeyid;                                             /*  key id used for BIP Key (tx key index) */
-       union Keytype   dot11wBIPKey[6];                /*  BIP Key, for index4 and index5 */
+       union Keytype   dot11wBIPKey[BIP_MAX_KEYID + 1];        /*  BIP Key, for index4 and index5 */
        union pn48              dot11wBIPtxpn;                  /*  PN48 used for Grp Key xmit. */
        union pn48              dot11wBIPrxpn;                  /*  PN48 used for Grp Key recv. */
 
index 54004f8..3aba4e6 100644 (file)
@@ -711,6 +711,7 @@ exit:
 static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
 {
        int ret = 0;
+       u8 max_idx;
        u32 wep_key_idx, wep_key_len;
        struct adapter *padapter = rtw_netdev_priv(dev);
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
@@ -724,26 +725,29 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param
                goto exit;
        }
 
-       if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
-           param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
-           param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
-               if (param->u.crypt.idx >= WEP_KEYS
-                       || param->u.crypt.idx >= BIP_MAX_KEYID) {
-                       ret = -EINVAL;
-                       goto exit;
-               }
-       } else {
-               {
+       if (param->sta_addr[0] != 0xff || param->sta_addr[1] != 0xff ||
+           param->sta_addr[2] != 0xff || param->sta_addr[3] != 0xff ||
+           param->sta_addr[4] != 0xff || param->sta_addr[5] != 0xff) {
                ret = -EINVAL;
                goto exit;
        }
+
+       if (strcmp(param->u.crypt.alg, "WEP") == 0)
+               max_idx = WEP_KEYS - 1;
+       else
+               max_idx = BIP_MAX_KEYID;
+
+       if (param->u.crypt.idx > max_idx) {
+               netdev_err(dev, "Error crypt.idx %d > %d\n", param->u.crypt.idx, max_idx);
+               ret = -EINVAL;
+               goto exit;
        }
 
        if (strcmp(param->u.crypt.alg, "WEP") == 0) {
                wep_key_idx = param->u.crypt.idx;
                wep_key_len = param->u.crypt.key_len;
 
-               if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
+               if (wep_key_len <= 0) {
                        ret = -EINVAL;
                        goto exit;
                }
index 30374a8..40a3157 100644 (file)
@@ -46,6 +46,7 @@ static int wpa_set_auth_algs(struct net_device *dev, u32 value)
 static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
 {
        int ret = 0;
+       u8 max_idx;
        u32 wep_key_idx, wep_key_len, wep_total_len;
        struct ndis_802_11_wep   *pwep = NULL;
        struct adapter *padapter = rtw_netdev_priv(dev);
@@ -60,19 +61,22 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
                goto exit;
        }
 
-       if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
-           param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
-           param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
-               if (param->u.crypt.idx >= WEP_KEYS ||
-                   param->u.crypt.idx >= BIP_MAX_KEYID) {
-                       ret = -EINVAL;
-                       goto exit;
-               }
-       } else {
-               {
-                       ret = -EINVAL;
-                       goto exit;
-               }
+       if (param->sta_addr[0] != 0xff || param->sta_addr[1] != 0xff ||
+           param->sta_addr[2] != 0xff || param->sta_addr[3] != 0xff ||
+           param->sta_addr[4] != 0xff || param->sta_addr[5] != 0xff) {
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       if (strcmp(param->u.crypt.alg, "WEP") == 0)
+               max_idx = WEP_KEYS - 1;
+       else
+               max_idx = BIP_MAX_KEYID;
+
+       if (param->u.crypt.idx > max_idx) {
+               netdev_err(dev, "Error crypt.idx %d > %d\n", param->u.crypt.idx, max_idx);
+               ret = -EINVAL;
+               goto exit;
        }
 
        if (strcmp(param->u.crypt.alg, "WEP") == 0) {
@@ -84,9 +88,6 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
                wep_key_idx = param->u.crypt.idx;
                wep_key_len = param->u.crypt.key_len;
 
-               if (wep_key_idx > WEP_KEYS)
-                       return -EINVAL;
-
                if (wep_key_len > 0) {
                        wep_key_len = wep_key_len <= 5 ? 5 : 13;
                        wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, key_material);