Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cfg80211/nl80211: separate unicast/multicast default TX keys

Allow userspace to specify that a given key
is default only for unicast and/or multicast
transmissions. Only WEP keys are for both,
WPA/RSN keys set here are GTKs for multicast
only. For more future flexibility, allow to
specify all combiations.

Wireless extensions can only set both so use
nl80211; WEP keys (connect keys) must be set
as default for both (but 802.1X WEP is still
possible).

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

authored by

Johannes Berg and committed by
John W. Linville
dbd2fd65 897bed8b

+153 -30
+2 -1
drivers/net/wireless/iwmc3200wifi/cfg80211.c
··· 225 225 226 226 static int iwm_cfg80211_set_default_key(struct wiphy *wiphy, 227 227 struct net_device *ndev, 228 - u8 key_index) 228 + u8 key_index, bool unicast, 229 + bool multicast) 229 230 { 230 231 struct iwm_priv *iwm = ndev_to_iwm(ndev); 231 232
+2 -1
drivers/net/wireless/libertas/cfg.c
··· 1422 1422 1423 1423 static int lbs_cfg_set_default_key(struct wiphy *wiphy, 1424 1424 struct net_device *netdev, 1425 - u8 key_index) 1425 + u8 key_index, bool unicast, 1426 + bool multicast) 1426 1427 { 1427 1428 struct lbs_private *priv = wiphy_priv(wiphy); 1428 1429
+2 -2
drivers/net/wireless/rndis_wlan.c
··· 554 554 u8 key_index, bool pairwise, const u8 *mac_addr); 555 555 556 556 static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev, 557 - u8 key_index); 557 + u8 key_index, bool unicast, bool multicast); 558 558 559 559 static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev, 560 560 u8 *mac, struct station_info *sinfo); ··· 2381 2381 } 2382 2382 2383 2383 static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev, 2384 - u8 key_index) 2384 + u8 key_index, bool unicast, bool multicast) 2385 2385 { 2386 2386 struct rndis_wlan_private *priv = wiphy_priv(wiphy); 2387 2387 struct usbnet *usbdev = priv->usbdev;
+27
include/linux/nl80211.h
··· 851 851 * 852 852 * @NL80211_ATTR_BSS_HTOPMODE: HT operation mode (u16) 853 853 * 854 + * @NL80211_ATTR_KEY_DEFAULT_TYPES: A nested attribute containing flags 855 + * attributes, specifying what a key should be set as default as. 856 + * See &enum nl80211_key_default_types. 857 + * 854 858 * @NL80211_ATTR_MAX: highest attribute number currently defined 855 859 * @__NL80211_ATTR_AFTER_LAST: internal use 856 860 */ ··· 1032 1028 NL80211_ATTR_OFFCHANNEL_TX_OK, 1033 1029 1034 1030 NL80211_ATTR_BSS_HT_OPMODE, 1031 + 1032 + NL80211_ATTR_KEY_DEFAULT_TYPES, 1035 1033 1036 1034 /* add attributes here, update the policy in nl80211.c */ 1037 1035 ··· 1781 1775 }; 1782 1776 1783 1777 /** 1778 + * enum nl80211_key_default_types - key default types 1779 + * @__NL80211_KEY_DEFAULT_TYPE_INVALID: invalid 1780 + * @NL80211_KEY_DEFAULT_TYPE_UNICAST: key should be used as default 1781 + * unicast key 1782 + * @NL80211_KEY_DEFAULT_TYPE_MULTICAST: key should be used as default 1783 + * multicast key 1784 + * @NUM_NL80211_KEY_DEFAULT_TYPES: number of default types 1785 + */ 1786 + enum nl80211_key_default_types { 1787 + __NL80211_KEY_DEFAULT_TYPE_INVALID, 1788 + NL80211_KEY_DEFAULT_TYPE_UNICAST, 1789 + NL80211_KEY_DEFAULT_TYPE_MULTICAST, 1790 + 1791 + NUM_NL80211_KEY_DEFAULT_TYPES 1792 + }; 1793 + 1794 + /** 1784 1795 * enum nl80211_key_attributes - key attributes 1785 1796 * @__NL80211_KEY_INVALID: invalid 1786 1797 * @NL80211_KEY_DATA: (temporal) key data; for TKIP this consists of ··· 1813 1790 * @NL80211_KEY_TYPE: the key type from enum nl80211_key_type, if not 1814 1791 * specified the default depends on whether a MAC address was 1815 1792 * given with the command using the key or not (u32) 1793 + * @NL80211_KEY_DEFAULT_TYPES: A nested attribute containing flags 1794 + * attributes, specifying what a key should be set as default as. 1795 + * See &enum nl80211_key_default_types. 1816 1796 * @__NL80211_KEY_AFTER_LAST: internal 1817 1797 * @NL80211_KEY_MAX: highest key attribute 1818 1798 */ ··· 1828 1802 NL80211_KEY_DEFAULT, 1829 1803 NL80211_KEY_DEFAULT_MGMT, 1830 1804 NL80211_KEY_TYPE, 1805 + NL80211_KEY_DEFAULT_TYPES, 1831 1806 1832 1807 /* keep last */ 1833 1808 __NL80211_KEY_AFTER_LAST,
+4 -1
include/net/cfg80211.h
··· 1211 1211 u8 key_index, bool pairwise, const u8 *mac_addr); 1212 1212 int (*set_default_key)(struct wiphy *wiphy, 1213 1213 struct net_device *netdev, 1214 - u8 key_index); 1214 + u8 key_index, bool unicast, bool multicast); 1215 1215 int (*set_default_mgmt_key)(struct wiphy *wiphy, 1216 1216 struct net_device *netdev, 1217 1217 u8 key_index); ··· 1393 1393 * control port protocol ethertype. The device also honours the 1394 1394 * control_port_no_encrypt flag. 1395 1395 * @WIPHY_FLAG_IBSS_RSN: The device supports IBSS RSN. 1396 + * @WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS: The device supports separate 1397 + * unicast and multicast TX keys. 1396 1398 */ 1397 1399 enum wiphy_flags { 1398 1400 WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0), ··· 1406 1404 WIPHY_FLAG_4ADDR_STATION = BIT(6), 1407 1405 WIPHY_FLAG_CONTROL_PORT_PROTOCOL = BIT(7), 1408 1406 WIPHY_FLAG_IBSS_RSN = BIT(8), 1407 + WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS= BIT(9), 1409 1408 }; 1410 1409 1411 1410 struct mac_address {
+2 -1
net/mac80211/cfg.c
··· 295 295 296 296 static int ieee80211_config_default_key(struct wiphy *wiphy, 297 297 struct net_device *dev, 298 - u8 key_idx) 298 + u8 key_idx, bool uni, 299 + bool multi) 299 300 { 300 301 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 301 302
+108 -19
net/wireless/nl80211.c
··· 171 171 [NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U32 }, 172 172 [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 }, 173 173 [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG }, 174 + [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED }, 174 175 }; 175 176 176 177 /* policy for the key attributes */ ··· 183 182 [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG }, 184 183 [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG }, 185 184 [NL80211_KEY_TYPE] = { .type = NLA_U32 }, 185 + [NL80211_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED }, 186 + }; 187 + 188 + /* policy for the key default flags */ 189 + static const struct nla_policy 190 + nl80211_key_default_policy[NUM_NL80211_KEY_DEFAULT_TYPES] = { 191 + [NL80211_KEY_DEFAULT_TYPE_UNICAST] = { .type = NLA_FLAG }, 192 + [NL80211_KEY_DEFAULT_TYPE_MULTICAST] = { .type = NLA_FLAG }, 186 193 }; 187 194 188 195 /* ifidx get helper */ ··· 323 314 int idx; 324 315 int type; 325 316 bool def, defmgmt; 317 + bool def_uni, def_multi; 326 318 }; 327 319 328 320 static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) ··· 336 326 337 327 k->def = !!tb[NL80211_KEY_DEFAULT]; 338 328 k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT]; 329 + 330 + if (k->def) { 331 + k->def_uni = true; 332 + k->def_multi = true; 333 + } 334 + if (k->defmgmt) 335 + k->def_multi = true; 339 336 340 337 if (tb[NL80211_KEY_IDX]) 341 338 k->idx = nla_get_u8(tb[NL80211_KEY_IDX]); ··· 364 347 k->type = nla_get_u32(tb[NL80211_KEY_TYPE]); 365 348 if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES) 366 349 return -EINVAL; 350 + } 351 + 352 + if (tb[NL80211_KEY_DEFAULT_TYPES]) { 353 + struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES]; 354 + int err = nla_parse_nested(kdt, 355 + NUM_NL80211_KEY_DEFAULT_TYPES - 1, 356 + tb[NL80211_KEY_DEFAULT_TYPES], 357 + nl80211_key_default_policy); 358 + if (err) 359 + return err; 360 + 361 + k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST]; 362 + k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST]; 367 363 } 368 364 369 365 return 0; ··· 403 373 k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT]; 404 374 k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]; 405 375 376 + if (k->def) { 377 + k->def_uni = true; 378 + k->def_multi = true; 379 + } 380 + if (k->defmgmt) 381 + k->def_multi = true; 382 + 406 383 if (info->attrs[NL80211_ATTR_KEY_TYPE]) { 407 384 k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]); 408 385 if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES) 409 386 return -EINVAL; 387 + } 388 + 389 + if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) { 390 + struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES]; 391 + int err = nla_parse_nested( 392 + kdt, NUM_NL80211_KEY_DEFAULT_TYPES - 1, 393 + info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES], 394 + nl80211_key_default_policy); 395 + if (err) 396 + return err; 397 + 398 + k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST]; 399 + k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST]; 410 400 } 411 401 412 402 return 0; ··· 450 400 451 401 if (k->def && k->defmgmt) 452 402 return -EINVAL; 403 + 404 + if (k->defmgmt) { 405 + if (k->def_uni || !k->def_multi) 406 + return -EINVAL; 407 + } 453 408 454 409 if (k->idx != -1) { 455 410 if (k->defmgmt) { ··· 505 450 goto error; 506 451 def = 1; 507 452 result->def = parse.idx; 453 + if (!parse.def_uni || !parse.def_multi) 454 + goto error; 508 455 } else if (parse.defmgmt) 509 456 goto error; 510 457 err = cfg80211_validate_key_settings(rdev, &parse.p, ··· 1643 1586 struct key_parse key; 1644 1587 int err; 1645 1588 struct net_device *dev = info->user_ptr[1]; 1646 - int (*func)(struct wiphy *wiphy, struct net_device *netdev, 1647 - u8 key_index); 1648 1589 1649 1590 err = nl80211_parse_key(info, &key); 1650 1591 if (err) ··· 1655 1600 if (!key.def && !key.defmgmt) 1656 1601 return -EINVAL; 1657 1602 1658 - if (key.def) 1659 - func = rdev->ops->set_default_key; 1660 - else 1661 - func = rdev->ops->set_default_mgmt_key; 1662 - 1663 - if (!func) 1664 - return -EOPNOTSUPP; 1665 - 1666 1603 wdev_lock(dev->ieee80211_ptr); 1667 - err = nl80211_key_allowed(dev->ieee80211_ptr); 1668 - if (!err) 1669 - err = func(&rdev->wiphy, dev, key.idx); 1604 + 1605 + if (key.def) { 1606 + if (!rdev->ops->set_default_key) { 1607 + err = -EOPNOTSUPP; 1608 + goto out; 1609 + } 1610 + 1611 + err = nl80211_key_allowed(dev->ieee80211_ptr); 1612 + if (err) 1613 + goto out; 1614 + 1615 + if (!(rdev->wiphy.flags & 1616 + WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS)) { 1617 + if (!key.def_uni || !key.def_multi) { 1618 + err = -EOPNOTSUPP; 1619 + goto out; 1620 + } 1621 + } 1622 + 1623 + err = rdev->ops->set_default_key(&rdev->wiphy, dev, key.idx, 1624 + key.def_uni, key.def_multi); 1625 + 1626 + if (err) 1627 + goto out; 1670 1628 1671 1629 #ifdef CONFIG_CFG80211_WEXT 1672 - if (!err) { 1673 - if (func == rdev->ops->set_default_key) 1674 - dev->ieee80211_ptr->wext.default_key = key.idx; 1675 - else 1676 - dev->ieee80211_ptr->wext.default_mgmt_key = key.idx; 1677 - } 1630 + dev->ieee80211_ptr->wext.default_key = key.idx; 1678 1631 #endif 1632 + } else { 1633 + if (key.def_uni || !key.def_multi) { 1634 + err = -EINVAL; 1635 + goto out; 1636 + } 1637 + 1638 + if (!rdev->ops->set_default_mgmt_key) { 1639 + err = -EOPNOTSUPP; 1640 + goto out; 1641 + } 1642 + 1643 + err = nl80211_key_allowed(dev->ieee80211_ptr); 1644 + if (err) 1645 + goto out; 1646 + 1647 + err = rdev->ops->set_default_mgmt_key(&rdev->wiphy, 1648 + dev, key.idx); 1649 + if (err) 1650 + goto out; 1651 + 1652 + #ifdef CONFIG_CFG80211_WEXT 1653 + dev->ieee80211_ptr->wext.default_mgmt_key = key.idx; 1654 + #endif 1655 + } 1656 + 1657 + out: 1679 1658 wdev_unlock(dev->ieee80211_ptr); 1680 1659 1681 1660 return err;
+2 -1
net/wireless/util.c
··· 689 689 continue; 690 690 } 691 691 if (wdev->connect_keys->def == i) 692 - if (rdev->ops->set_default_key(wdev->wiphy, dev, i)) { 692 + if (rdev->ops->set_default_key(wdev->wiphy, dev, 693 + i, true, true)) { 693 694 netdev_err(dev, "failed to set defkey %d\n", i); 694 695 continue; 695 696 }
+4 -4
net/wireless/wext-compat.c
··· 548 548 __cfg80211_leave_ibss(rdev, wdev->netdev, true); 549 549 rejoin = true; 550 550 } 551 - err = rdev->ops->set_default_key(&rdev->wiphy, 552 - dev, idx); 551 + err = rdev->ops->set_default_key(&rdev->wiphy, dev, 552 + idx, true, true); 553 553 } 554 554 if (!err) { 555 555 wdev->wext.default_key = idx; ··· 627 627 err = 0; 628 628 wdev_lock(wdev); 629 629 if (wdev->current_bss) 630 - err = rdev->ops->set_default_key(&rdev->wiphy, 631 - dev, idx); 630 + err = rdev->ops->set_default_key(&rdev->wiphy, dev, 631 + idx, true, true); 632 632 if (!err) 633 633 wdev->wext.default_key = idx; 634 634 wdev_unlock(wdev);