예제 #1
0
static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
				   struct net_device *dev, const u8 *addr,
				   bool remove, bool tx_key, int idx,
				   struct key_params *params)
{
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	int err;

	if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
		if (!rdev->ops->set_default_mgmt_key)
			return -EOPNOTSUPP;

		if (idx < 4 || idx > 5)
			return -EINVAL;
	} else if (idx < 0 || idx > 3)
		return -EINVAL;

	if (remove) {
		err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr);
		if (!err) {
			if (idx == wdev->wext.default_key)
				wdev->wext.default_key = -1;
			else if (idx == wdev->wext.default_mgmt_key)
				wdev->wext.default_mgmt_key = -1;
		}
		/*
		 * Applications using wireless extensions expect to be
		 * able to delete keys that don't exist, so allow that.
		 */
		if (err == -ENOENT)
			return 0;

		return err;
	} else {
		if (addr)
			tx_key = false;

		if (cfg80211_validate_key_settings(params, idx, addr))
			return -EINVAL;

		err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params);
		if (err)
			return err;

		if (tx_key || (!addr && wdev->wext.default_key == -1)) {
			err = rdev->ops->set_default_key(&rdev->wiphy,
							 dev, idx);
			if (!err)
				wdev->wext.default_key = idx;
			return err;
		}

		if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC &&
		    (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) {
			err = rdev->ops->set_default_mgmt_key(&rdev->wiphy,
							      dev, idx);
			if (!err)
				wdev->wext.default_mgmt_key = idx;
			return err;
		}

		return 0;
	}
}
예제 #2
0
static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
				     struct net_device *dev, bool pairwise,
				     const u8 *addr, bool remove, bool tx_key,
				     int idx, struct key_params *params)
{
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	int err, i;
	bool rejoin = false;

	if (pairwise && !addr)
		return -EINVAL;

	if (!wdev->wext.keys) {
		wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys),
					      GFP_KERNEL);
		if (!wdev->wext.keys)
			return -ENOMEM;
		for (i = 0; i < 6; i++)
			wdev->wext.keys->params[i].key =
				wdev->wext.keys->data[i];
	}

	if (wdev->iftype != NL80211_IFTYPE_ADHOC &&
	    wdev->iftype != NL80211_IFTYPE_STATION)
		return -EOPNOTSUPP;

	if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
		if (!wdev->current_bss)
			return -ENOLINK;

		if (!rdev->ops->set_default_mgmt_key)
			return -EOPNOTSUPP;

		if (idx < 4 || idx > 5)
			return -EINVAL;
	} else if (idx < 0 || idx > 3)
		return -EINVAL;

	if (remove) {
		err = 0;
		if (wdev->current_bss) {
			/*
			 * If removing the current TX key, we will need to
			 * join a new IBSS without the privacy bit clear.
			 */
			if (idx == wdev->wext.default_key &&
			    wdev->iftype == NL80211_IFTYPE_ADHOC) {
				__cfg80211_leave_ibss(rdev, wdev->netdev, true);
				rejoin = true;
			}

			if (!pairwise && addr &&
			    !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
				err = -ENOENT;
			else
				err = rdev->ops->del_key(&rdev->wiphy, dev, idx,
							 pairwise, addr);
		}
		wdev->wext.connect.privacy = false;
		/*
		 * Applications using wireless extensions expect to be
		 * able to delete keys that don't exist, so allow that.
		 */
		if (err == -ENOENT)
			err = 0;
		if (!err) {
			if (!addr) {
				wdev->wext.keys->params[idx].key_len = 0;
				wdev->wext.keys->params[idx].cipher = 0;
			}
			if (idx == wdev->wext.default_key)
				wdev->wext.default_key = -1;
			else if (idx == wdev->wext.default_mgmt_key)
				wdev->wext.default_mgmt_key = -1;
		}

		if (!err && rejoin)
			err = cfg80211_ibss_wext_join(rdev, wdev);

		return err;
	}

	if (addr)
		tx_key = false;

	if (cfg80211_validate_key_settings(rdev, params, idx, pairwise, addr))
		return -EINVAL;

	err = 0;
	if (wdev->current_bss)
		err = rdev->ops->add_key(&rdev->wiphy, dev, idx,
					 pairwise, addr, params);
	if (err)
		return err;

	if (!addr) {
		wdev->wext.keys->params[idx] = *params;
		memcpy(wdev->wext.keys->data[idx],
			params->key, params->key_len);
		wdev->wext.keys->params[idx].key =
			wdev->wext.keys->data[idx];
	}

	if ((params->cipher == WLAN_CIPHER_SUITE_WEP40 ||
	     params->cipher == WLAN_CIPHER_SUITE_WEP104) &&
	    (tx_key || (!addr && wdev->wext.default_key == -1))) {
		if (wdev->current_bss) {
			/*
			 * If we are getting a new TX key from not having
			 * had one before we need to join a new IBSS with
			 * the privacy bit set.
			 */
			if (wdev->iftype == NL80211_IFTYPE_ADHOC &&
			    wdev->wext.default_key == -1) {
				__cfg80211_leave_ibss(rdev, wdev->netdev, true);
				rejoin = true;
			}
			err = rdev->ops->set_default_key(&rdev->wiphy, dev,
							 idx, true, true);
		}
		if (!err) {
			wdev->wext.default_key = idx;
			if (rejoin)
				err = cfg80211_ibss_wext_join(rdev, wdev);
		}
		return err;
	}

	if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC &&
	    (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) {
		if (wdev->current_bss)
			err = rdev->ops->set_default_mgmt_key(&rdev->wiphy,
							      dev, idx);
		if (!err)
			wdev->wext.default_mgmt_key = idx;
		return err;
	}

	return 0;
}
예제 #3
0
static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
				     struct net_device *dev, const u8 *addr,
				     bool remove, bool tx_key, int idx,
				     struct key_params *params)
{
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	int err, i;

	if (!wdev->wext.keys) {
		wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys),
					      GFP_KERNEL);
		if (!wdev->wext.keys)
			return -ENOMEM;
		for (i = 0; i < 6; i++)
			wdev->wext.keys->params[i].key =
				wdev->wext.keys->data[i];
	}

	if (wdev->iftype != NL80211_IFTYPE_ADHOC &&
	    wdev->iftype != NL80211_IFTYPE_STATION)
		return -EOPNOTSUPP;

	if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
		if (!wdev->current_bss)
			return -ENOLINK;

		if (!rdev->ops->set_default_mgmt_key)
			return -EOPNOTSUPP;

		if (idx < 4 || idx > 5)
			return -EINVAL;
	} else if (idx < 0 || idx > 3)
		return -EINVAL;

	if (remove) {
		err = 0;
		if (wdev->current_bss)
			err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr);
		if (!err) {
			if (!addr) {
				wdev->wext.keys->params[idx].key_len = 0;
				wdev->wext.keys->params[idx].cipher = 0;
			}
			if (idx == wdev->wext.default_key)
				wdev->wext.default_key = -1;
			else if (idx == wdev->wext.default_mgmt_key)
				wdev->wext.default_mgmt_key = -1;
		}
		/*
		 * Applications using wireless extensions expect to be
		 * able to delete keys that don't exist, so allow that.
		 */
		if (err == -ENOENT)
			return 0;

		return err;
	}

	if (addr)
		tx_key = false;

	if (cfg80211_validate_key_settings(rdev, params, idx, addr))
		return -EINVAL;

	err = 0;
	if (wdev->current_bss)
		err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params);
	if (err)
		return err;

	if (!addr) {
		wdev->wext.keys->params[idx] = *params;
		memcpy(wdev->wext.keys->data[idx],
			params->key, params->key_len);
		wdev->wext.keys->params[idx].key =
			wdev->wext.keys->data[idx];
	}

	if ((params->cipher == WLAN_CIPHER_SUITE_WEP40 ||
	     params->cipher == WLAN_CIPHER_SUITE_WEP104) &&
	    (tx_key || (!addr && wdev->wext.default_key == -1))) {
		if (wdev->current_bss)
			err = rdev->ops->set_default_key(&rdev->wiphy,
							 dev, idx);
		if (!err)
			wdev->wext.default_key = idx;
		return err;
	}

	if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC &&
	    (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) {
		if (wdev->current_bss)
			err = rdev->ops->set_default_mgmt_key(&rdev->wiphy,
							      dev, idx);
		if (!err)
			wdev->wext.default_mgmt_key = idx;
		return err;
	}

	return 0;
}