|
|
@@ -452,16 +452,16 @@ static void convert_key_from_CPU(struct brcmf_wsec_key *key,
|
|
|
}
|
|
|
|
|
|
static int
|
|
|
-send_key_to_dongle(struct net_device *ndev, struct brcmf_wsec_key *key)
|
|
|
+send_key_to_dongle(struct brcmf_if *ifp, struct brcmf_wsec_key *key)
|
|
|
{
|
|
|
int err;
|
|
|
struct brcmf_wsec_key_le key_le;
|
|
|
|
|
|
convert_key_from_CPU(key, &key_le);
|
|
|
|
|
|
- brcmf_netdev_wait_pend8021x(ndev);
|
|
|
+ brcmf_netdev_wait_pend8021x(ifp);
|
|
|
|
|
|
- err = brcmf_fil_bsscfg_data_set(netdev_priv(ndev), "wsec_key", &key_le,
|
|
|
+ err = brcmf_fil_bsscfg_data_set(ifp, "wsec_key", &key_le,
|
|
|
sizeof(key_le));
|
|
|
|
|
|
if (err)
|
|
|
@@ -1670,7 +1670,7 @@ brcmf_set_sharedkey(struct net_device *ndev,
|
|
|
brcmf_dbg(CONN, "key length (%d) key index (%d) algo (%d)\n",
|
|
|
key.len, key.index, key.algo);
|
|
|
brcmf_dbg(CONN, "key \"%s\"\n", key.data);
|
|
|
- err = send_key_to_dongle(ndev, &key);
|
|
|
+ err = send_key_to_dongle(netdev_priv(ndev), &key);
|
|
|
if (err)
|
|
|
return err;
|
|
|
|
|
|
@@ -2052,7 +2052,7 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
|
|
|
/* check for key index change */
|
|
|
if (key.len == 0) {
|
|
|
/* key delete */
|
|
|
- err = send_key_to_dongle(ndev, &key);
|
|
|
+ err = send_key_to_dongle(ifp, &key);
|
|
|
if (err)
|
|
|
brcmf_err("key delete error (%d)\n", err);
|
|
|
} else {
|
|
|
@@ -2108,7 +2108,7 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
|
|
|
brcmf_err("Invalid cipher (0x%x)\n", params->cipher);
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
- err = send_key_to_dongle(ndev, &key);
|
|
|
+ err = send_key_to_dongle(ifp, &key);
|
|
|
if (err)
|
|
|
brcmf_err("wsec_key error (%d)\n", err);
|
|
|
}
|
|
|
@@ -2121,7 +2121,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
|
|
|
struct key_params *params)
|
|
|
{
|
|
|
struct brcmf_if *ifp = netdev_priv(ndev);
|
|
|
- struct brcmf_wsec_key key;
|
|
|
+ struct brcmf_wsec_key *key;
|
|
|
s32 val;
|
|
|
s32 wsec;
|
|
|
s32 err = 0;
|
|
|
@@ -2132,54 +2132,62 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
|
|
|
if (!check_vif_up(ifp->vif))
|
|
|
return -EIO;
|
|
|
|
|
|
+ if (key_idx >= BRCMF_MAX_DEFAULT_KEYS) {
|
|
|
+ /* we ignore this key index in this case */
|
|
|
+ brcmf_err("invalid key index (%d)\n", key_idx);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
if (mac_addr &&
|
|
|
(params->cipher != WLAN_CIPHER_SUITE_WEP40) &&
|
|
|
(params->cipher != WLAN_CIPHER_SUITE_WEP104)) {
|
|
|
brcmf_dbg(TRACE, "Exit");
|
|
|
return brcmf_add_keyext(wiphy, ndev, key_idx, mac_addr, params);
|
|
|
}
|
|
|
- memset(&key, 0, sizeof(key));
|
|
|
|
|
|
- key.len = (u32) params->key_len;
|
|
|
- key.index = (u32) key_idx;
|
|
|
+ key = &ifp->vif->profile.key[key_idx];
|
|
|
+ memset(key, 0, sizeof(*key));
|
|
|
|
|
|
- if (key.len > sizeof(key.data)) {
|
|
|
- brcmf_err("Too long key length (%u)\n", key.len);
|
|
|
+ if (params->key_len > sizeof(key->data)) {
|
|
|
+ brcmf_err("Too long key length (%u)\n", params->key_len);
|
|
|
err = -EINVAL;
|
|
|
goto done;
|
|
|
}
|
|
|
- memcpy(key.data, params->key, key.len);
|
|
|
+ key->len = params->key_len;
|
|
|
+ key->index = key_idx;
|
|
|
|
|
|
- key.flags = BRCMF_PRIMARY_KEY;
|
|
|
+ memcpy(key->data, params->key, key->len);
|
|
|
+
|
|
|
+ key->flags = BRCMF_PRIMARY_KEY;
|
|
|
switch (params->cipher) {
|
|
|
case WLAN_CIPHER_SUITE_WEP40:
|
|
|
- key.algo = CRYPTO_ALGO_WEP1;
|
|
|
+ key->algo = CRYPTO_ALGO_WEP1;
|
|
|
val = WEP_ENABLED;
|
|
|
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP40\n");
|
|
|
break;
|
|
|
case WLAN_CIPHER_SUITE_WEP104:
|
|
|
- key.algo = CRYPTO_ALGO_WEP128;
|
|
|
+ key->algo = CRYPTO_ALGO_WEP128;
|
|
|
val = WEP_ENABLED;
|
|
|
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");
|
|
|
break;
|
|
|
case WLAN_CIPHER_SUITE_TKIP:
|
|
|
if (!brcmf_is_apmode(ifp->vif)) {
|
|
|
brcmf_dbg(CONN, "Swapping RX/TX MIC key\n");
|
|
|
- memcpy(keybuf, &key.data[24], sizeof(keybuf));
|
|
|
- memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
|
|
|
- memcpy(&key.data[16], keybuf, sizeof(keybuf));
|
|
|
+ memcpy(keybuf, &key->data[24], sizeof(keybuf));
|
|
|
+ memcpy(&key->data[24], &key->data[16], sizeof(keybuf));
|
|
|
+ memcpy(&key->data[16], keybuf, sizeof(keybuf));
|
|
|
}
|
|
|
- key.algo = CRYPTO_ALGO_TKIP;
|
|
|
+ key->algo = CRYPTO_ALGO_TKIP;
|
|
|
val = TKIP_ENABLED;
|
|
|
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n");
|
|
|
break;
|
|
|
case WLAN_CIPHER_SUITE_AES_CMAC:
|
|
|
- key.algo = CRYPTO_ALGO_AES_CCM;
|
|
|
+ key->algo = CRYPTO_ALGO_AES_CCM;
|
|
|
val = AES_ENABLED;
|
|
|
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");
|
|
|
break;
|
|
|
case WLAN_CIPHER_SUITE_CCMP:
|
|
|
- key.algo = CRYPTO_ALGO_AES_CCM;
|
|
|
+ key->algo = CRYPTO_ALGO_AES_CCM;
|
|
|
val = AES_ENABLED;
|
|
|
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_CCMP\n");
|
|
|
break;
|
|
|
@@ -2189,7 +2197,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
|
|
|
goto done;
|
|
|
}
|
|
|
|
|
|
- err = send_key_to_dongle(ndev, &key);
|
|
|
+ err = send_key_to_dongle(ifp, key);
|
|
|
if (err)
|
|
|
goto done;
|
|
|
|
|
|
@@ -2222,7 +2230,7 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
|
|
|
if (!check_vif_up(ifp->vif))
|
|
|
return -EIO;
|
|
|
|
|
|
- if (key_idx >= DOT11_MAX_DEFAULT_KEYS) {
|
|
|
+ if (key_idx >= BRCMF_MAX_DEFAULT_KEYS) {
|
|
|
/* we ignore this key index in this case */
|
|
|
brcmf_err("invalid key index (%d)\n", key_idx);
|
|
|
return -EINVAL;
|
|
|
@@ -2237,7 +2245,7 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
|
|
|
brcmf_dbg(CONN, "key index (%d)\n", key_idx);
|
|
|
|
|
|
/* Set the new key/index */
|
|
|
- err = send_key_to_dongle(ndev, &key);
|
|
|
+ err = send_key_to_dongle(ifp, &key);
|
|
|
|
|
|
brcmf_dbg(TRACE, "Exit\n");
|
|
|
return err;
|
|
|
@@ -2305,6 +2313,39 @@ brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
|
|
|
return -EOPNOTSUPP;
|
|
|
}
|
|
|
|
|
|
+static void
|
|
|
+brcmf_cfg80211_reconfigure_wep(struct brcmf_if *ifp)
|
|
|
+{
|
|
|
+ s32 err;
|
|
|
+ u8 key_idx;
|
|
|
+ struct brcmf_wsec_key *key;
|
|
|
+ s32 wsec;
|
|
|
+
|
|
|
+ for (key_idx = 0; key_idx < BRCMF_MAX_DEFAULT_KEYS; key_idx++) {
|
|
|
+ key = &ifp->vif->profile.key[key_idx];
|
|
|
+ if ((key->algo == CRYPTO_ALGO_WEP1) ||
|
|
|
+ (key->algo == CRYPTO_ALGO_WEP128))
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (key_idx == BRCMF_MAX_DEFAULT_KEYS)
|
|
|
+ return;
|
|
|
+
|
|
|
+ err = send_key_to_dongle(ifp, key);
|
|
|
+ if (err) {
|
|
|
+ brcmf_err("Setting WEP key failed (%d)\n", err);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
|
|
|
+ if (err) {
|
|
|
+ brcmf_err("get wsec error (%d)\n", err);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ wsec |= WEP_ENABLED;
|
|
|
+ err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);
|
|
|
+ if (err)
|
|
|
+ brcmf_err("set wsec error (%d)\n", err);
|
|
|
+}
|
|
|
+
|
|
|
static s32
|
|
|
brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
|
|
|
const u8 *mac, struct station_info *sinfo)
|
|
|
@@ -4057,6 +4098,10 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
|
|
|
brcmf_err("BRCMF_C_UP error (%d)\n", err);
|
|
|
goto exit;
|
|
|
}
|
|
|
+ /* On DOWN the firmware removes the WEP keys, reconfigure
|
|
|
+ * them if they were set.
|
|
|
+ */
|
|
|
+ brcmf_cfg80211_reconfigure_wep(ifp);
|
|
|
|
|
|
memset(&join_params, 0, sizeof(join_params));
|
|
|
/* join parameters starts with ssid */
|