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

cfg80211: Support key configuration for Beacon protection (BIGTK)

IEEE P802.11-REVmd/D3.0 adds support for protecting Beacon frames using
a new set of keys (BIGTK; key index 6..7) similarly to the way
group-addressed Robust Management frames are protected (IGTK; key index
4..5). Extend cfg80211 and nl80211 to allow the new BIGTK to be
configured. Add an extended feature flag to indicate driver support for
the new key index values to avoid array overflows in driver
implementations and also to indicate to user space when this
functionality is available.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
Link: https://lore.kernel.org/r/20200222132548.20835-2-jouni@codeaurora.org
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Jouni Malinen and committed by
Johannes Berg
56be393f f8af764b

+101 -14
+5
include/net/cfg80211.h
··· 3369 3369 * @set_default_key: set the default key on an interface 3370 3370 * 3371 3371 * @set_default_mgmt_key: set the default management frame key on an interface 3372 + 3373 + * @set_default_beacon_key: set the default Beacon frame key on an interface 3372 3374 * 3373 3375 * @set_rekey_data: give the data necessary for GTK rekeying to the driver 3374 3376 * ··· 3704 3702 int (*set_default_mgmt_key)(struct wiphy *wiphy, 3705 3703 struct net_device *netdev, 3706 3704 u8 key_index); 3705 + int (*set_default_beacon_key)(struct wiphy *wiphy, 3706 + struct net_device *netdev, 3707 + u8 key_index); 3707 3708 3708 3709 int (*start_ap)(struct wiphy *wiphy, struct net_device *dev, 3709 3710 struct cfg80211_ap_settings *settings);
+6
include/uapi/linux/nl80211.h
··· 4550 4550 * See &enum nl80211_key_default_types. 4551 4551 * @NL80211_KEY_MODE: the mode from enum nl80211_key_mode. 4552 4552 * Defaults to @NL80211_KEY_RX_TX. 4553 + * @NL80211_KEY_DEFAULT_BEACON: flag indicating default Beacon frame key 4553 4554 * 4554 4555 * @__NL80211_KEY_AFTER_LAST: internal 4555 4556 * @NL80211_KEY_MAX: highest key attribute ··· 4566 4565 NL80211_KEY_TYPE, 4567 4566 NL80211_KEY_DEFAULT_TYPES, 4568 4567 NL80211_KEY_MODE, 4568 + NL80211_KEY_DEFAULT_BEACON, 4569 4569 4570 4570 /* keep last */ 4571 4571 __NL80211_KEY_AFTER_LAST, ··· 5541 5539 * feature, which prevents bufferbloat by using the expected transmission 5542 5540 * time to limit the amount of data buffered in the hardware. 5543 5541 * 5542 + * @NL80211_EXT_FEATURE_BEACON_PROTECTION: The driver supports Beacon protection 5543 + * and can receive key configuration for BIGTK using key indexes 6 and 7. 5544 + * 5544 5545 * @NUM_NL80211_EXT_FEATURES: number of extended features. 5545 5546 * @MAX_NL80211_EXT_FEATURES: highest extended feature index. 5546 5547 */ ··· 5591 5586 NL80211_EXT_FEATURE_SAE_OFFLOAD, 5592 5587 NL80211_EXT_FEATURE_VLAN_OFFLOAD, 5593 5588 NL80211_EXT_FEATURE_AQL, 5589 + NL80211_EXT_FEATURE_BEACON_PROTECTION, 5594 5590 5595 5591 /* add new features before the definition below */ 5596 5592 NUM_NL80211_EXT_FEATURES,
+45 -11
net/wireless/nl80211.c
··· 368 368 [NL80211_ATTR_KEY] = { .type = NLA_NESTED, }, 369 369 [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY, 370 370 .len = WLAN_MAX_KEY_LEN }, 371 - [NL80211_ATTR_KEY_IDX] = NLA_POLICY_MAX(NLA_U8, 5), 371 + [NL80211_ATTR_KEY_IDX] = NLA_POLICY_MAX(NLA_U8, 7), 372 372 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 }, 373 373 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG }, 374 374 [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 }, ··· 1037 1037 struct key_params p; 1038 1038 int idx; 1039 1039 int type; 1040 - bool def, defmgmt; 1040 + bool def, defmgmt, defbeacon; 1041 1041 bool def_uni, def_multi; 1042 1042 }; 1043 1043 ··· 1053 1053 1054 1054 k->def = !!tb[NL80211_KEY_DEFAULT]; 1055 1055 k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT]; 1056 + k->defbeacon = !!tb[NL80211_KEY_DEFAULT_BEACON]; 1056 1057 1057 1058 if (k->def) { 1058 1059 k->def_uni = true; 1059 1060 k->def_multi = true; 1060 1061 } 1061 - if (k->defmgmt) 1062 + if (k->defmgmt || k->defbeacon) 1062 1063 k->def_multi = true; 1063 1064 1064 1065 if (tb[NL80211_KEY_IDX]) ··· 1166 1165 if (err) 1167 1166 return err; 1168 1167 1169 - if (k->def && k->defmgmt) { 1170 - GENL_SET_ERR_MSG(info, "key with def && defmgmt is invalid"); 1168 + if ((k->def ? 1 : 0) + (k->defmgmt ? 1 : 0) + 1169 + (k->defbeacon ? 1 : 0) > 1) { 1170 + GENL_SET_ERR_MSG(info, 1171 + "key with multiple default flags is invalid"); 1171 1172 return -EINVAL; 1172 1173 } 1173 1174 1174 - if (k->defmgmt) { 1175 + if (k->defmgmt || k->defbeacon) { 1175 1176 if (k->def_uni || !k->def_multi) { 1176 - GENL_SET_ERR_MSG(info, "defmgmt key must be mcast"); 1177 + GENL_SET_ERR_MSG(info, 1178 + "defmgmt/defbeacon key must be mcast"); 1177 1179 return -EINVAL; 1178 1180 } 1179 1181 } ··· 1188 1184 "defmgmt key idx not 4 or 5"); 1189 1185 return -EINVAL; 1190 1186 } 1187 + } else if (k->defbeacon) { 1188 + if (k->idx < 6 || k->idx > 7) { 1189 + GENL_SET_ERR_MSG(info, 1190 + "defbeacon key idx not 6 or 7"); 1191 + return -EINVAL; 1192 + } 1191 1193 } else if (k->def) { 1192 1194 if (k->idx < 0 || k->idx > 3) { 1193 1195 GENL_SET_ERR_MSG(info, "def key idx not 0-3"); 1194 1196 return -EINVAL; 1195 1197 } 1196 1198 } else { 1197 - if (k->idx < 0 || k->idx > 5) { 1198 - GENL_SET_ERR_MSG(info, "key idx not 0-5"); 1199 + if (k->idx < 0 || k->idx > 7) { 1200 + GENL_SET_ERR_MSG(info, "key idx not 0-7"); 1199 1201 return -EINVAL; 1200 1202 } 1201 1203 } ··· 3827 3817 void *hdr; 3828 3818 struct sk_buff *msg; 3829 3819 3830 - if (info->attrs[NL80211_ATTR_KEY_IDX]) 3820 + if (info->attrs[NL80211_ATTR_KEY_IDX]) { 3831 3821 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); 3822 + if (key_idx > 5 && 3823 + !wiphy_ext_feature_isset( 3824 + &rdev->wiphy, 3825 + NL80211_EXT_FEATURE_BEACON_PROTECTION)) 3826 + return -EINVAL; 3827 + } 3832 3828 3833 3829 if (info->attrs[NL80211_ATTR_MAC]) 3834 3830 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); ··· 3910 3894 /* Only support setting default key and 3911 3895 * Extended Key ID action NL80211_KEY_SET_TX. 3912 3896 */ 3913 - if (!key.def && !key.defmgmt && 3897 + if (!key.def && !key.defmgmt && !key.defbeacon && 3914 3898 !(key.p.mode == NL80211_KEY_SET_TX)) 3915 3899 return -EINVAL; 3916 3900 ··· 3957 3941 #ifdef CONFIG_CFG80211_WEXT 3958 3942 dev->ieee80211_ptr->wext.default_mgmt_key = key.idx; 3959 3943 #endif 3944 + } else if (key.defbeacon) { 3945 + if (key.def_uni || !key.def_multi) { 3946 + err = -EINVAL; 3947 + goto out; 3948 + } 3949 + 3950 + if (!rdev->ops->set_default_beacon_key) { 3951 + err = -EOPNOTSUPP; 3952 + goto out; 3953 + } 3954 + 3955 + err = nl80211_key_allowed(dev->ieee80211_ptr); 3956 + if (err) 3957 + goto out; 3958 + 3959 + err = rdev_set_default_beacon_key(rdev, dev, key.idx); 3960 + if (err) 3961 + goto out; 3960 3962 } else if (key.p.mode == NL80211_KEY_SET_TX && 3961 3963 wiphy_ext_feature_isset(&rdev->wiphy, 3962 3964 NL80211_EXT_FEATURE_EXT_KEY_ID)) {
+13
net/wireless/rdev-ops.h
··· 136 136 return ret; 137 137 } 138 138 139 + static inline int 140 + rdev_set_default_beacon_key(struct cfg80211_registered_device *rdev, 141 + struct net_device *netdev, u8 key_index) 142 + { 143 + int ret; 144 + 145 + trace_rdev_set_default_beacon_key(&rdev->wiphy, netdev, key_index); 146 + ret = rdev->ops->set_default_beacon_key(&rdev->wiphy, netdev, 147 + key_index); 148 + trace_rdev_return_int(&rdev->wiphy, ret); 149 + return ret; 150 + } 151 + 139 152 static inline int rdev_start_ap(struct cfg80211_registered_device *rdev, 140 153 struct net_device *dev, 141 154 struct cfg80211_ap_settings *settings)
+9 -2
net/wireless/sme.c
··· 1111 1111 * Delete all the keys ... pairwise keys can't really 1112 1112 * exist any more anyway, but default keys might. 1113 1113 */ 1114 - if (rdev->ops->del_key) 1115 - for (i = 0; i < 6; i++) 1114 + if (rdev->ops->del_key) { 1115 + int max_key_idx = 5; 1116 + 1117 + if (wiphy_ext_feature_isset( 1118 + wdev->wiphy, 1119 + NL80211_EXT_FEATURE_BEACON_PROTECTION)) 1120 + max_key_idx = 7; 1121 + for (i = 0; i <= max_key_idx; i++) 1116 1122 rdev_del_key(rdev, dev, i, false, NULL); 1123 + } 1117 1124 1118 1125 rdev_set_qos_map(rdev, dev, NULL); 1119 1126
+17
net/wireless/trace.h
··· 510 510 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index) 511 511 ); 512 512 513 + TRACE_EVENT(rdev_set_default_beacon_key, 514 + TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index), 515 + TP_ARGS(wiphy, netdev, key_index), 516 + TP_STRUCT__entry( 517 + WIPHY_ENTRY 518 + NETDEV_ENTRY 519 + __field(u8, key_index) 520 + ), 521 + TP_fast_assign( 522 + WIPHY_ASSIGN; 523 + NETDEV_ASSIGN; 524 + __entry->key_index = key_index; 525 + ), 526 + TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key index: %u", 527 + WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index) 528 + ); 529 + 513 530 TRACE_EVENT(rdev_start_ap, 514 531 TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, 515 532 struct cfg80211_ap_settings *settings),
+6 -1
net/wireless/util.c
··· 231 231 struct key_params *params, int key_idx, 232 232 bool pairwise, const u8 *mac_addr) 233 233 { 234 - if (key_idx < 0 || key_idx > 5) 234 + int max_key_idx = 5; 235 + 236 + if (wiphy_ext_feature_isset(&rdev->wiphy, 237 + NL80211_EXT_FEATURE_BEACON_PROTECTION)) 238 + max_key_idx = 7; 239 + if (key_idx < 0 || key_idx > max_key_idx) 235 240 return -EINVAL; 236 241 237 242 if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))