1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright 2003-2005 Devicescape Software, Inc. 4 * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> 5 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> 6 * Copyright (C) 2015 Intel Deutschland GmbH 7 * Copyright (C) 2021-2023, 2026 Intel Corporation 8 */ 9 10 #include <linux/kobject.h> 11 #include <linux/slab.h> 12 #include "ieee80211_i.h" 13 #include "key.h" 14 #include "debugfs.h" 15 #include "debugfs_key.h" 16 17 #define KEY_READ(name, prop, format_string) \ 18 static ssize_t key_##name##_read(struct file *file, \ 19 char __user *userbuf, \ 20 size_t count, loff_t *ppos) \ 21 { \ 22 struct ieee80211_key *key = file->private_data; \ 23 return mac80211_format_buffer(userbuf, count, ppos, \ 24 format_string, key->prop); \ 25 } 26 #define KEY_READ_X(name) KEY_READ(name, name, "0x%x\n") 27 28 #define KEY_OPS(name) \ 29 static const struct debugfs_short_fops key_ ##name## _ops = { \ 30 .read = key_##name##_read, \ 31 .llseek = generic_file_llseek, \ 32 } 33 34 #define KEY_OPS_W(name) \ 35 static const struct debugfs_short_fops key_ ##name## _ops = { \ 36 .read = key_##name##_read, \ 37 .write = key_##name##_write, \ 38 .llseek = generic_file_llseek, \ 39 } 40 41 #define KEY_FILE(name, format) \ 42 KEY_READ_##format(name) \ 43 KEY_OPS(name) 44 45 #define KEY_CONF_READ(name, val, format_string) \ 46 KEY_READ(conf_##name, conf.val, format_string) 47 #define KEY_CONF_READ_D(name, val) KEY_CONF_READ(name, val, "%d\n") 48 #define KEY_CONF_READ_X(name, val) KEY_CONF_READ(name, val, "0x%x\n") 49 50 #define KEY_CONF_OPS(name) \ 51 static const struct debugfs_short_fops key_ ##name## _ops = { \ 52 .read = key_conf_##name##_read, \ 53 .llseek = generic_file_llseek, \ 54 } 55 56 #define KEY_CONF_FILE(name, format) \ 57 KEY_CONF_READ_##format(name, name) \ 58 KEY_CONF_OPS(name) 59 #define KEY_CONF_FILE_NAMED(name, val, format) \ 60 KEY_CONF_READ_##format(name, val) \ 61 KEY_CONF_OPS(name) 62 63 KEY_CONF_FILE(keylen, D); 64 KEY_CONF_FILE(keyidx, D); 65 KEY_CONF_FILE(hw_key_idx, D); 66 KEY_CONF_FILE_NAMED(conf_flags, flags, X); 67 KEY_FILE(flags, X); 68 KEY_CONF_FILE(link_id, D); 69 KEY_READ(ifindex, sdata->name, "%s\n"); 70 KEY_OPS(ifindex); 71 72 static ssize_t key_algorithm_read(struct file *file, 73 char __user *userbuf, 74 size_t count, loff_t *ppos) 75 { 76 char buf[15]; 77 struct ieee80211_key *key = file->private_data; 78 u32 c = key->conf.cipher; 79 80 sprintf(buf, "%.2x-%.2x-%.2x:%d\n", 81 c >> 24, (c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff); 82 return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf)); 83 } 84 KEY_OPS(algorithm); 85 86 static ssize_t key_tx_spec_write(struct file *file, const char __user *userbuf, 87 size_t count, loff_t *ppos) 88 { 89 struct ieee80211_key *key = file->private_data; 90 u64 pn; 91 int ret; 92 93 switch (key->conf.cipher) { 94 case WLAN_CIPHER_SUITE_WEP40: 95 case WLAN_CIPHER_SUITE_WEP104: 96 return -EINVAL; 97 case WLAN_CIPHER_SUITE_TKIP: 98 /* not supported yet */ 99 return -EOPNOTSUPP; 100 case WLAN_CIPHER_SUITE_CCMP: 101 case WLAN_CIPHER_SUITE_CCMP_256: 102 case WLAN_CIPHER_SUITE_AES_CMAC: 103 case WLAN_CIPHER_SUITE_BIP_CMAC_256: 104 case WLAN_CIPHER_SUITE_BIP_GMAC_128: 105 case WLAN_CIPHER_SUITE_BIP_GMAC_256: 106 case WLAN_CIPHER_SUITE_GCMP: 107 case WLAN_CIPHER_SUITE_GCMP_256: 108 ret = kstrtou64_from_user(userbuf, count, 16, &pn); 109 if (ret) 110 return ret; 111 /* PN is a 48-bit counter */ 112 if (pn >= (1ULL << 48)) 113 return -ERANGE; 114 atomic64_set(&key->conf.tx_pn, pn); 115 return count; 116 default: 117 return 0; 118 } 119 } 120 121 static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, 122 size_t count, loff_t *ppos) 123 { 124 u64 pn; 125 char buf[20]; 126 int len; 127 struct ieee80211_key *key = file->private_data; 128 129 switch (key->conf.cipher) { 130 case WLAN_CIPHER_SUITE_WEP40: 131 case WLAN_CIPHER_SUITE_WEP104: 132 len = scnprintf(buf, sizeof(buf), "\n"); 133 break; 134 case WLAN_CIPHER_SUITE_TKIP: 135 pn = atomic64_read(&key->conf.tx_pn); 136 len = scnprintf(buf, sizeof(buf), "%08x %04x\n", 137 TKIP_PN_TO_IV32(pn), 138 TKIP_PN_TO_IV16(pn)); 139 break; 140 case WLAN_CIPHER_SUITE_CCMP: 141 case WLAN_CIPHER_SUITE_CCMP_256: 142 case WLAN_CIPHER_SUITE_AES_CMAC: 143 case WLAN_CIPHER_SUITE_BIP_CMAC_256: 144 case WLAN_CIPHER_SUITE_BIP_GMAC_128: 145 case WLAN_CIPHER_SUITE_BIP_GMAC_256: 146 case WLAN_CIPHER_SUITE_GCMP: 147 case WLAN_CIPHER_SUITE_GCMP_256: 148 pn = atomic64_read(&key->conf.tx_pn); 149 len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", 150 (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), 151 (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); 152 break; 153 default: 154 return 0; 155 } 156 return simple_read_from_buffer(userbuf, count, ppos, buf, len); 157 } 158 KEY_OPS_W(tx_spec); 159 160 static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, 161 size_t count, loff_t *ppos) 162 { 163 struct ieee80211_key *key = file->private_data; 164 char buf[14*IEEE80211_NUM_TIDS+1], *p = buf; 165 int i, len; 166 const u8 *rpn; 167 168 switch (key->conf.cipher) { 169 case WLAN_CIPHER_SUITE_WEP40: 170 case WLAN_CIPHER_SUITE_WEP104: 171 len = scnprintf(buf, sizeof(buf), "\n"); 172 break; 173 case WLAN_CIPHER_SUITE_TKIP: 174 for (i = 0; i < IEEE80211_NUM_TIDS; i++) 175 p += scnprintf(p, sizeof(buf)+buf-p, 176 "%08x %04x\n", 177 key->u.tkip.rx[i].iv32, 178 key->u.tkip.rx[i].iv16); 179 len = p - buf; 180 break; 181 case WLAN_CIPHER_SUITE_CCMP: 182 case WLAN_CIPHER_SUITE_CCMP_256: 183 for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) { 184 rpn = key->u.ccmp.rx_pn[i]; 185 p += scnprintf(p, sizeof(buf)+buf-p, 186 "%02x%02x%02x%02x%02x%02x\n", 187 rpn[0], rpn[1], rpn[2], 188 rpn[3], rpn[4], rpn[5]); 189 } 190 len = p - buf; 191 break; 192 case WLAN_CIPHER_SUITE_AES_CMAC: 193 case WLAN_CIPHER_SUITE_BIP_CMAC_256: 194 rpn = key->u.aes_cmac.rx_pn; 195 p += scnprintf(p, sizeof(buf)+buf-p, 196 "%02x%02x%02x%02x%02x%02x\n", 197 rpn[0], rpn[1], rpn[2], 198 rpn[3], rpn[4], rpn[5]); 199 len = p - buf; 200 break; 201 case WLAN_CIPHER_SUITE_BIP_GMAC_128: 202 case WLAN_CIPHER_SUITE_BIP_GMAC_256: 203 rpn = key->u.aes_gmac.rx_pn; 204 p += scnprintf(p, sizeof(buf)+buf-p, 205 "%02x%02x%02x%02x%02x%02x\n", 206 rpn[0], rpn[1], rpn[2], 207 rpn[3], rpn[4], rpn[5]); 208 len = p - buf; 209 break; 210 case WLAN_CIPHER_SUITE_GCMP: 211 case WLAN_CIPHER_SUITE_GCMP_256: 212 for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) { 213 rpn = key->u.gcmp.rx_pn[i]; 214 p += scnprintf(p, sizeof(buf)+buf-p, 215 "%02x%02x%02x%02x%02x%02x\n", 216 rpn[0], rpn[1], rpn[2], 217 rpn[3], rpn[4], rpn[5]); 218 } 219 len = p - buf; 220 break; 221 default: 222 return 0; 223 } 224 return simple_read_from_buffer(userbuf, count, ppos, buf, len); 225 } 226 KEY_OPS(rx_spec); 227 228 static ssize_t key_replays_read(struct file *file, char __user *userbuf, 229 size_t count, loff_t *ppos) 230 { 231 struct ieee80211_key *key = file->private_data; 232 char buf[20]; 233 int len; 234 235 switch (key->conf.cipher) { 236 case WLAN_CIPHER_SUITE_CCMP: 237 case WLAN_CIPHER_SUITE_CCMP_256: 238 len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays); 239 break; 240 case WLAN_CIPHER_SUITE_AES_CMAC: 241 case WLAN_CIPHER_SUITE_BIP_CMAC_256: 242 len = scnprintf(buf, sizeof(buf), "%u\n", 243 key->u.aes_cmac.replays); 244 break; 245 case WLAN_CIPHER_SUITE_BIP_GMAC_128: 246 case WLAN_CIPHER_SUITE_BIP_GMAC_256: 247 len = scnprintf(buf, sizeof(buf), "%u\n", 248 key->u.aes_gmac.replays); 249 break; 250 case WLAN_CIPHER_SUITE_GCMP: 251 case WLAN_CIPHER_SUITE_GCMP_256: 252 len = scnprintf(buf, sizeof(buf), "%u\n", key->u.gcmp.replays); 253 break; 254 default: 255 return 0; 256 } 257 return simple_read_from_buffer(userbuf, count, ppos, buf, len); 258 } 259 KEY_OPS(replays); 260 261 static ssize_t key_icverrors_read(struct file *file, char __user *userbuf, 262 size_t count, loff_t *ppos) 263 { 264 struct ieee80211_key *key = file->private_data; 265 char buf[20]; 266 int len; 267 268 switch (key->conf.cipher) { 269 case WLAN_CIPHER_SUITE_AES_CMAC: 270 case WLAN_CIPHER_SUITE_BIP_CMAC_256: 271 len = scnprintf(buf, sizeof(buf), "%u\n", 272 key->u.aes_cmac.icverrors); 273 break; 274 case WLAN_CIPHER_SUITE_BIP_GMAC_128: 275 case WLAN_CIPHER_SUITE_BIP_GMAC_256: 276 len = scnprintf(buf, sizeof(buf), "%u\n", 277 key->u.aes_gmac.icverrors); 278 break; 279 default: 280 return 0; 281 } 282 return simple_read_from_buffer(userbuf, count, ppos, buf, len); 283 } 284 KEY_OPS(icverrors); 285 286 static ssize_t key_mic_failures_read(struct file *file, char __user *userbuf, 287 size_t count, loff_t *ppos) 288 { 289 struct ieee80211_key *key = file->private_data; 290 char buf[20]; 291 int len; 292 293 if (key->conf.cipher != WLAN_CIPHER_SUITE_TKIP) 294 return -EINVAL; 295 296 len = scnprintf(buf, sizeof(buf), "%u\n", key->u.tkip.mic_failures); 297 298 return simple_read_from_buffer(userbuf, count, ppos, buf, len); 299 } 300 KEY_OPS(mic_failures); 301 302 static ssize_t key_key_read(struct file *file, char __user *userbuf, 303 size_t count, loff_t *ppos) 304 { 305 struct ieee80211_key *key = file->private_data; 306 int i, bufsize = 2 * key->conf.keylen + 2; 307 char *buf = kmalloc(bufsize, GFP_KERNEL); 308 char *p = buf; 309 ssize_t res; 310 311 if (!buf) 312 return -ENOMEM; 313 314 for (i = 0; i < key->conf.keylen; i++) 315 p += scnprintf(p, bufsize + buf - p, "%02x", key->conf.key[i]); 316 p += scnprintf(p, bufsize+buf-p, "\n"); 317 res = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); 318 kfree(buf); 319 return res; 320 } 321 KEY_OPS(key); 322 323 #define DEBUGFS_ADD(name) \ 324 debugfs_create_file(#name, 0400, key->debugfs.dir, \ 325 key, &key_##name##_ops) 326 #define DEBUGFS_ADD_W(name) \ 327 debugfs_create_file(#name, 0600, key->debugfs.dir, \ 328 key, &key_##name##_ops); 329 330 void ieee80211_debugfs_key_add(struct ieee80211_key *key) 331 { 332 static int keycount; 333 char buf[100]; 334 struct sta_info *sta; 335 336 if (!key->local->debugfs.keys) 337 return; 338 339 sprintf(buf, "%d", keycount); 340 key->debugfs.cnt = keycount; 341 keycount++; 342 key->debugfs.dir = debugfs_create_dir(buf, 343 key->local->debugfs.keys); 344 345 sta = key->sta; 346 if (sta) { 347 sprintf(buf, "../../netdev:%s/stations/%pM", 348 sta->sdata->name, sta->sta.addr); 349 key->debugfs.stalink = 350 debugfs_create_symlink("station", key->debugfs.dir, buf); 351 } 352 353 DEBUGFS_ADD(keylen); 354 DEBUGFS_ADD(flags); 355 DEBUGFS_ADD(keyidx); 356 DEBUGFS_ADD(hw_key_idx); 357 DEBUGFS_ADD(algorithm); 358 DEBUGFS_ADD_W(tx_spec); 359 DEBUGFS_ADD(rx_spec); 360 DEBUGFS_ADD(replays); 361 DEBUGFS_ADD(icverrors); 362 DEBUGFS_ADD(mic_failures); 363 DEBUGFS_ADD(key); 364 DEBUGFS_ADD(ifindex); 365 DEBUGFS_ADD(conf_flags); 366 DEBUGFS_ADD(link_id); 367 }; 368 369 void ieee80211_debugfs_key_remove(struct ieee80211_key *key) 370 { 371 if (!key) 372 return; 373 374 debugfs_remove_recursive(key->debugfs.dir); 375 key->debugfs.dir = NULL; 376 } 377 378 void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) 379 { 380 char buf[50]; 381 struct ieee80211_key *key; 382 383 if (!sdata->vif.debugfs_dir) 384 return; 385 386 lockdep_assert_wiphy(sdata->local->hw.wiphy); 387 388 debugfs_remove(sdata->debugfs.default_unicast_key); 389 sdata->debugfs.default_unicast_key = NULL; 390 391 if (sdata->default_unicast_key) { 392 key = wiphy_dereference(sdata->local->hw.wiphy, 393 sdata->default_unicast_key); 394 sprintf(buf, "../keys/%d", key->debugfs.cnt); 395 sdata->debugfs.default_unicast_key = 396 debugfs_create_symlink("default_unicast_key", 397 sdata->vif.debugfs_dir, buf); 398 } 399 400 debugfs_remove(sdata->debugfs.default_multicast_key); 401 sdata->debugfs.default_multicast_key = NULL; 402 403 if (sdata->deflink.default_multicast_key) { 404 key = wiphy_dereference(sdata->local->hw.wiphy, 405 sdata->deflink.default_multicast_key); 406 sprintf(buf, "../keys/%d", key->debugfs.cnt); 407 sdata->debugfs.default_multicast_key = 408 debugfs_create_symlink("default_multicast_key", 409 sdata->vif.debugfs_dir, buf); 410 } 411 } 412 413 void ieee80211_debugfs_key_remove_mgmt_default(struct ieee80211_sub_if_data *sdata) 414 { 415 if (!sdata) 416 return; 417 418 debugfs_remove(sdata->debugfs.default_mgmt_key); 419 sdata->debugfs.default_mgmt_key = NULL; 420 } 421 422 void 423 ieee80211_debugfs_key_remove_beacon_default(struct ieee80211_sub_if_data *sdata) 424 { 425 if (!sdata) 426 return; 427 428 debugfs_remove(sdata->debugfs.default_beacon_key); 429 sdata->debugfs.default_beacon_key = NULL; 430 } 431