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

mac80211: support separate default keys

Add support for split default keys (unicast
and multicast) in mac80211.

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
f7e0104c dbd2fd65

+62 -47
+1 -1
net/mac80211/cfg.c
··· 300 300 { 301 301 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 302 302 303 - ieee80211_set_default_key(sdata, key_idx); 303 + ieee80211_set_default_key(sdata, key_idx, uni, multi); 304 304 305 305 return 0; 306 306 }
+21 -16
net/mac80211/debugfs_key.c
··· 274 274 debugfs_remove_recursive(key->debugfs.dir); 275 275 key->debugfs.dir = NULL; 276 276 } 277 - void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata) 277 + 278 + void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) 278 279 { 279 280 char buf[50]; 280 281 struct ieee80211_key *key; ··· 283 282 if (!sdata->debugfs.dir) 284 283 return; 285 284 286 - /* this is running under the key lock */ 285 + lockdep_assert_held(&sdata->local->key_mtx); 287 286 288 - key = sdata->default_key; 289 - if (key) { 287 + if (sdata->default_unicast_key) { 288 + key = sdata->default_unicast_key; 290 289 sprintf(buf, "../keys/%d", key->debugfs.cnt); 291 - sdata->debugfs.default_key = 292 - debugfs_create_symlink("default_key", 290 + sdata->debugfs.default_unicast_key = 291 + debugfs_create_symlink("default_unicast_key", 293 292 sdata->debugfs.dir, buf); 294 - } else 295 - ieee80211_debugfs_key_remove_default(sdata); 296 - } 293 + } else { 294 + debugfs_remove(sdata->debugfs.default_unicast_key); 295 + sdata->debugfs.default_unicast_key = NULL; 296 + } 297 297 298 - void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata) 299 - { 300 - if (!sdata) 301 - return; 302 - 303 - debugfs_remove(sdata->debugfs.default_key); 304 - sdata->debugfs.default_key = NULL; 298 + if (sdata->default_multicast_key) { 299 + key = sdata->default_multicast_key; 300 + sprintf(buf, "../keys/%d", key->debugfs.cnt); 301 + sdata->debugfs.default_multicast_key = 302 + debugfs_create_symlink("default_multicast_key", 303 + sdata->debugfs.dir, buf); 304 + } else { 305 + debugfs_remove(sdata->debugfs.default_multicast_key); 306 + sdata->debugfs.default_multicast_key = NULL; 307 + } 305 308 } 306 309 307 310 void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata)
+2 -6
net/mac80211/debugfs_key.h
··· 4 4 #ifdef CONFIG_MAC80211_DEBUGFS 5 5 void ieee80211_debugfs_key_add(struct ieee80211_key *key); 6 6 void ieee80211_debugfs_key_remove(struct ieee80211_key *key); 7 - void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata); 8 - void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata); 7 + void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata); 9 8 void ieee80211_debugfs_key_add_mgmt_default( 10 9 struct ieee80211_sub_if_data *sdata); 11 10 void ieee80211_debugfs_key_remove_mgmt_default( ··· 16 17 {} 17 18 static inline void ieee80211_debugfs_key_remove(struct ieee80211_key *key) 18 19 {} 19 - static inline void ieee80211_debugfs_key_add_default( 20 - struct ieee80211_sub_if_data *sdata) 21 - {} 22 - static inline void ieee80211_debugfs_key_remove_default( 20 + static inline void ieee80211_debugfs_key_update_default( 23 21 struct ieee80211_sub_if_data *sdata) 24 22 {} 25 23 static inline void ieee80211_debugfs_key_add_mgmt_default(
+3 -2
net/mac80211/ieee80211_i.h
··· 557 557 unsigned int fragment_next; 558 558 559 559 struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; 560 - struct ieee80211_key *default_key; 560 + struct ieee80211_key *default_unicast_key, *default_multicast_key; 561 561 struct ieee80211_key *default_mgmt_key; 562 562 563 563 u16 sequence_number; ··· 595 595 struct { 596 596 struct dentry *dir; 597 597 struct dentry *subdir_stations; 598 - struct dentry *default_key; 598 + struct dentry *default_unicast_key; 599 + struct dentry *default_multicast_key; 599 600 struct dentry *default_mgmt_key; 600 601 } debugfs; 601 602 #endif
+26 -19
net/mac80211/key.c
··· 178 178 EXPORT_SYMBOL_GPL(ieee80211_key_removed); 179 179 180 180 static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, 181 - int idx) 181 + int idx, bool uni, bool multi) 182 182 { 183 183 struct ieee80211_key *key = NULL; 184 184 ··· 187 187 if (idx >= 0 && idx < NUM_DEFAULT_KEYS) 188 188 key = sdata->keys[idx]; 189 189 190 - rcu_assign_pointer(sdata->default_key, key); 190 + if (uni) 191 + rcu_assign_pointer(sdata->default_unicast_key, key); 192 + if (multi) 193 + rcu_assign_pointer(sdata->default_multicast_key, key); 191 194 192 - if (key) { 193 - ieee80211_debugfs_key_remove_default(key->sdata); 194 - ieee80211_debugfs_key_add_default(key->sdata); 195 - } 195 + ieee80211_debugfs_key_update_default(sdata); 196 196 } 197 197 198 - void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx) 198 + void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, 199 + bool uni, bool multi) 199 200 { 200 201 mutex_lock(&sdata->local->key_mtx); 201 - __ieee80211_set_default_key(sdata, idx); 202 + __ieee80211_set_default_key(sdata, idx, uni, multi); 202 203 mutex_unlock(&sdata->local->key_mtx); 203 204 } 204 205 ··· 216 215 217 216 rcu_assign_pointer(sdata->default_mgmt_key, key); 218 217 219 - if (key) { 220 - ieee80211_debugfs_key_remove_mgmt_default(key->sdata); 221 - ieee80211_debugfs_key_add_mgmt_default(key->sdata); 222 - } 218 + ieee80211_debugfs_key_update_default(sdata); 223 219 } 224 220 225 221 void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, ··· 234 236 struct ieee80211_key *old, 235 237 struct ieee80211_key *new) 236 238 { 237 - int idx, defkey, defmgmtkey; 239 + int idx; 240 + bool defunikey, defmultikey, defmgmtkey; 238 241 239 242 if (new) 240 243 list_add(&new->list, &sdata->key_list); ··· 256 257 else 257 258 idx = new->conf.keyidx; 258 259 259 - defkey = old && sdata->default_key == old; 260 + defunikey = old && sdata->default_unicast_key == old; 261 + defmultikey = old && sdata->default_multicast_key == old; 260 262 defmgmtkey = old && sdata->default_mgmt_key == old; 261 263 262 - if (defkey && !new) 263 - __ieee80211_set_default_key(sdata, -1); 264 + if (defunikey && !new) 265 + __ieee80211_set_default_key(sdata, -1, true, false); 266 + if (defmultikey && !new) 267 + __ieee80211_set_default_key(sdata, -1, false, true); 264 268 if (defmgmtkey && !new) 265 269 __ieee80211_set_default_mgmt_key(sdata, -1); 266 270 267 271 rcu_assign_pointer(sdata->keys[idx], new); 268 - if (defkey && new) 269 - __ieee80211_set_default_key(sdata, new->conf.keyidx); 272 + if (defunikey && new) 273 + __ieee80211_set_default_key(sdata, new->conf.keyidx, 274 + true, false); 275 + if (defmultikey && new) 276 + __ieee80211_set_default_key(sdata, new->conf.keyidx, 277 + false, true); 270 278 if (defmgmtkey && new) 271 279 __ieee80211_set_default_mgmt_key(sdata, 272 280 new->conf.keyidx); ··· 515 509 516 510 mutex_lock(&sdata->local->key_mtx); 517 511 518 - ieee80211_debugfs_key_remove_default(sdata); 519 512 ieee80211_debugfs_key_remove_mgmt_default(sdata); 520 513 521 514 list_for_each_entry_safe(key, tmp, &sdata->key_list, list) 522 515 __ieee80211_key_free(key); 516 + 517 + ieee80211_debugfs_key_update_default(sdata); 523 518 524 519 mutex_unlock(&sdata->local->key_mtx); 525 520 }
+2 -1
net/mac80211/key.h
··· 138 138 struct sta_info *sta); 139 139 void ieee80211_key_free(struct ieee80211_local *local, 140 140 struct ieee80211_key *key); 141 - void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx); 141 + void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, 142 + bool uni, bool multi); 142 143 void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, 143 144 int idx); 144 145 void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata);
+2 -1
net/mac80211/main.c
··· 519 519 520 520 wiphy->flags |= WIPHY_FLAG_NETNS_OK | 521 521 WIPHY_FLAG_4ADDR_AP | 522 - WIPHY_FLAG_4ADDR_STATION; 522 + WIPHY_FLAG_4ADDR_STATION | 523 + WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS; 523 524 wiphy->privid = mac80211_wiphy_privid; 524 525 525 526 wiphy->bss_priv_size = sizeof(struct ieee80211_bss);
+5 -1
net/mac80211/tx.c
··· 539 539 ieee80211_is_robust_mgmt_frame(hdr) && 540 540 (key = rcu_dereference(tx->sdata->default_mgmt_key))) 541 541 tx->key = key; 542 - else if ((key = rcu_dereference(tx->sdata->default_key))) 542 + else if (is_multicast_ether_addr(hdr->addr1) && 543 + (key = rcu_dereference(tx->sdata->default_multicast_key))) 544 + tx->key = key; 545 + else if (!is_multicast_ether_addr(hdr->addr1) && 546 + (key = rcu_dereference(tx->sdata->default_unicast_key))) 543 547 tx->key = key; 544 548 else if (tx->sdata->drop_unencrypted && 545 549 (tx->skb->protocol != tx->sdata->control_port_protocol) &&