162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright 2003-2005 Devicescape Software, Inc. 462306a36Sopenharmony_ci * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> 562306a36Sopenharmony_ci * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> 662306a36Sopenharmony_ci * Copyright (C) 2015 Intel Deutschland GmbH 762306a36Sopenharmony_ci * Copyright (C) 2021-2022 Intel Corporation 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/kobject.h> 1162306a36Sopenharmony_ci#include <linux/slab.h> 1262306a36Sopenharmony_ci#include "ieee80211_i.h" 1362306a36Sopenharmony_ci#include "key.h" 1462306a36Sopenharmony_ci#include "debugfs.h" 1562306a36Sopenharmony_ci#include "debugfs_key.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#define KEY_READ(name, prop, format_string) \ 1862306a36Sopenharmony_cistatic ssize_t key_##name##_read(struct file *file, \ 1962306a36Sopenharmony_ci char __user *userbuf, \ 2062306a36Sopenharmony_ci size_t count, loff_t *ppos) \ 2162306a36Sopenharmony_ci{ \ 2262306a36Sopenharmony_ci struct ieee80211_key *key = file->private_data; \ 2362306a36Sopenharmony_ci return mac80211_format_buffer(userbuf, count, ppos, \ 2462306a36Sopenharmony_ci format_string, key->prop); \ 2562306a36Sopenharmony_ci} 2662306a36Sopenharmony_ci#define KEY_READ_X(name) KEY_READ(name, name, "0x%x\n") 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define KEY_OPS(name) \ 2962306a36Sopenharmony_cistatic const struct file_operations key_ ##name## _ops = { \ 3062306a36Sopenharmony_ci .read = key_##name##_read, \ 3162306a36Sopenharmony_ci .open = simple_open, \ 3262306a36Sopenharmony_ci .llseek = generic_file_llseek, \ 3362306a36Sopenharmony_ci} 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#define KEY_OPS_W(name) \ 3662306a36Sopenharmony_cistatic const struct file_operations key_ ##name## _ops = { \ 3762306a36Sopenharmony_ci .read = key_##name##_read, \ 3862306a36Sopenharmony_ci .write = key_##name##_write, \ 3962306a36Sopenharmony_ci .open = simple_open, \ 4062306a36Sopenharmony_ci .llseek = generic_file_llseek, \ 4162306a36Sopenharmony_ci} 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci#define KEY_FILE(name, format) \ 4462306a36Sopenharmony_ci KEY_READ_##format(name) \ 4562306a36Sopenharmony_ci KEY_OPS(name) 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#define KEY_CONF_READ(name, format_string) \ 4862306a36Sopenharmony_ci KEY_READ(conf_##name, conf.name, format_string) 4962306a36Sopenharmony_ci#define KEY_CONF_READ_D(name) KEY_CONF_READ(name, "%d\n") 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci#define KEY_CONF_OPS(name) \ 5262306a36Sopenharmony_cistatic const struct file_operations key_ ##name## _ops = { \ 5362306a36Sopenharmony_ci .read = key_conf_##name##_read, \ 5462306a36Sopenharmony_ci .open = simple_open, \ 5562306a36Sopenharmony_ci .llseek = generic_file_llseek, \ 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci#define KEY_CONF_FILE(name, format) \ 5962306a36Sopenharmony_ci KEY_CONF_READ_##format(name) \ 6062306a36Sopenharmony_ci KEY_CONF_OPS(name) 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ciKEY_CONF_FILE(keylen, D); 6362306a36Sopenharmony_ciKEY_CONF_FILE(keyidx, D); 6462306a36Sopenharmony_ciKEY_CONF_FILE(hw_key_idx, D); 6562306a36Sopenharmony_ciKEY_FILE(flags, X); 6662306a36Sopenharmony_ciKEY_READ(ifindex, sdata->name, "%s\n"); 6762306a36Sopenharmony_ciKEY_OPS(ifindex); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic ssize_t key_algorithm_read(struct file *file, 7062306a36Sopenharmony_ci char __user *userbuf, 7162306a36Sopenharmony_ci size_t count, loff_t *ppos) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci char buf[15]; 7462306a36Sopenharmony_ci struct ieee80211_key *key = file->private_data; 7562306a36Sopenharmony_ci u32 c = key->conf.cipher; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci sprintf(buf, "%.2x-%.2x-%.2x:%d\n", 7862306a36Sopenharmony_ci c >> 24, (c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff); 7962306a36Sopenharmony_ci return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf)); 8062306a36Sopenharmony_ci} 8162306a36Sopenharmony_ciKEY_OPS(algorithm); 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistatic ssize_t key_tx_spec_write(struct file *file, const char __user *userbuf, 8462306a36Sopenharmony_ci size_t count, loff_t *ppos) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci struct ieee80211_key *key = file->private_data; 8762306a36Sopenharmony_ci u64 pn; 8862306a36Sopenharmony_ci int ret; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci switch (key->conf.cipher) { 9162306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_WEP40: 9262306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_WEP104: 9362306a36Sopenharmony_ci return -EINVAL; 9462306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_TKIP: 9562306a36Sopenharmony_ci /* not supported yet */ 9662306a36Sopenharmony_ci return -EOPNOTSUPP; 9762306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_CCMP: 9862306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_CCMP_256: 9962306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_AES_CMAC: 10062306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_BIP_CMAC_256: 10162306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_BIP_GMAC_128: 10262306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_BIP_GMAC_256: 10362306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_GCMP: 10462306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_GCMP_256: 10562306a36Sopenharmony_ci ret = kstrtou64_from_user(userbuf, count, 16, &pn); 10662306a36Sopenharmony_ci if (ret) 10762306a36Sopenharmony_ci return ret; 10862306a36Sopenharmony_ci /* PN is a 48-bit counter */ 10962306a36Sopenharmony_ci if (pn >= (1ULL << 48)) 11062306a36Sopenharmony_ci return -ERANGE; 11162306a36Sopenharmony_ci atomic64_set(&key->conf.tx_pn, pn); 11262306a36Sopenharmony_ci return count; 11362306a36Sopenharmony_ci default: 11462306a36Sopenharmony_ci return 0; 11562306a36Sopenharmony_ci } 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_cistatic ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, 11962306a36Sopenharmony_ci size_t count, loff_t *ppos) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci u64 pn; 12262306a36Sopenharmony_ci char buf[20]; 12362306a36Sopenharmony_ci int len; 12462306a36Sopenharmony_ci struct ieee80211_key *key = file->private_data; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci switch (key->conf.cipher) { 12762306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_WEP40: 12862306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_WEP104: 12962306a36Sopenharmony_ci len = scnprintf(buf, sizeof(buf), "\n"); 13062306a36Sopenharmony_ci break; 13162306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_TKIP: 13262306a36Sopenharmony_ci pn = atomic64_read(&key->conf.tx_pn); 13362306a36Sopenharmony_ci len = scnprintf(buf, sizeof(buf), "%08x %04x\n", 13462306a36Sopenharmony_ci TKIP_PN_TO_IV32(pn), 13562306a36Sopenharmony_ci TKIP_PN_TO_IV16(pn)); 13662306a36Sopenharmony_ci break; 13762306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_CCMP: 13862306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_CCMP_256: 13962306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_AES_CMAC: 14062306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_BIP_CMAC_256: 14162306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_BIP_GMAC_128: 14262306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_BIP_GMAC_256: 14362306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_GCMP: 14462306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_GCMP_256: 14562306a36Sopenharmony_ci pn = atomic64_read(&key->conf.tx_pn); 14662306a36Sopenharmony_ci len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", 14762306a36Sopenharmony_ci (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), 14862306a36Sopenharmony_ci (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); 14962306a36Sopenharmony_ci break; 15062306a36Sopenharmony_ci default: 15162306a36Sopenharmony_ci return 0; 15262306a36Sopenharmony_ci } 15362306a36Sopenharmony_ci return simple_read_from_buffer(userbuf, count, ppos, buf, len); 15462306a36Sopenharmony_ci} 15562306a36Sopenharmony_ciKEY_OPS_W(tx_spec); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_cistatic ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, 15862306a36Sopenharmony_ci size_t count, loff_t *ppos) 15962306a36Sopenharmony_ci{ 16062306a36Sopenharmony_ci struct ieee80211_key *key = file->private_data; 16162306a36Sopenharmony_ci char buf[14*IEEE80211_NUM_TIDS+1], *p = buf; 16262306a36Sopenharmony_ci int i, len; 16362306a36Sopenharmony_ci const u8 *rpn; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci switch (key->conf.cipher) { 16662306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_WEP40: 16762306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_WEP104: 16862306a36Sopenharmony_ci len = scnprintf(buf, sizeof(buf), "\n"); 16962306a36Sopenharmony_ci break; 17062306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_TKIP: 17162306a36Sopenharmony_ci for (i = 0; i < IEEE80211_NUM_TIDS; i++) 17262306a36Sopenharmony_ci p += scnprintf(p, sizeof(buf)+buf-p, 17362306a36Sopenharmony_ci "%08x %04x\n", 17462306a36Sopenharmony_ci key->u.tkip.rx[i].iv32, 17562306a36Sopenharmony_ci key->u.tkip.rx[i].iv16); 17662306a36Sopenharmony_ci len = p - buf; 17762306a36Sopenharmony_ci break; 17862306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_CCMP: 17962306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_CCMP_256: 18062306a36Sopenharmony_ci for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) { 18162306a36Sopenharmony_ci rpn = key->u.ccmp.rx_pn[i]; 18262306a36Sopenharmony_ci p += scnprintf(p, sizeof(buf)+buf-p, 18362306a36Sopenharmony_ci "%02x%02x%02x%02x%02x%02x\n", 18462306a36Sopenharmony_ci rpn[0], rpn[1], rpn[2], 18562306a36Sopenharmony_ci rpn[3], rpn[4], rpn[5]); 18662306a36Sopenharmony_ci } 18762306a36Sopenharmony_ci len = p - buf; 18862306a36Sopenharmony_ci break; 18962306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_AES_CMAC: 19062306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_BIP_CMAC_256: 19162306a36Sopenharmony_ci rpn = key->u.aes_cmac.rx_pn; 19262306a36Sopenharmony_ci p += scnprintf(p, sizeof(buf)+buf-p, 19362306a36Sopenharmony_ci "%02x%02x%02x%02x%02x%02x\n", 19462306a36Sopenharmony_ci rpn[0], rpn[1], rpn[2], 19562306a36Sopenharmony_ci rpn[3], rpn[4], rpn[5]); 19662306a36Sopenharmony_ci len = p - buf; 19762306a36Sopenharmony_ci break; 19862306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_BIP_GMAC_128: 19962306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_BIP_GMAC_256: 20062306a36Sopenharmony_ci rpn = key->u.aes_gmac.rx_pn; 20162306a36Sopenharmony_ci p += scnprintf(p, sizeof(buf)+buf-p, 20262306a36Sopenharmony_ci "%02x%02x%02x%02x%02x%02x\n", 20362306a36Sopenharmony_ci rpn[0], rpn[1], rpn[2], 20462306a36Sopenharmony_ci rpn[3], rpn[4], rpn[5]); 20562306a36Sopenharmony_ci len = p - buf; 20662306a36Sopenharmony_ci break; 20762306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_GCMP: 20862306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_GCMP_256: 20962306a36Sopenharmony_ci for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) { 21062306a36Sopenharmony_ci rpn = key->u.gcmp.rx_pn[i]; 21162306a36Sopenharmony_ci p += scnprintf(p, sizeof(buf)+buf-p, 21262306a36Sopenharmony_ci "%02x%02x%02x%02x%02x%02x\n", 21362306a36Sopenharmony_ci rpn[0], rpn[1], rpn[2], 21462306a36Sopenharmony_ci rpn[3], rpn[4], rpn[5]); 21562306a36Sopenharmony_ci } 21662306a36Sopenharmony_ci len = p - buf; 21762306a36Sopenharmony_ci break; 21862306a36Sopenharmony_ci default: 21962306a36Sopenharmony_ci return 0; 22062306a36Sopenharmony_ci } 22162306a36Sopenharmony_ci return simple_read_from_buffer(userbuf, count, ppos, buf, len); 22262306a36Sopenharmony_ci} 22362306a36Sopenharmony_ciKEY_OPS(rx_spec); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_cistatic ssize_t key_replays_read(struct file *file, char __user *userbuf, 22662306a36Sopenharmony_ci size_t count, loff_t *ppos) 22762306a36Sopenharmony_ci{ 22862306a36Sopenharmony_ci struct ieee80211_key *key = file->private_data; 22962306a36Sopenharmony_ci char buf[20]; 23062306a36Sopenharmony_ci int len; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci switch (key->conf.cipher) { 23362306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_CCMP: 23462306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_CCMP_256: 23562306a36Sopenharmony_ci len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays); 23662306a36Sopenharmony_ci break; 23762306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_AES_CMAC: 23862306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_BIP_CMAC_256: 23962306a36Sopenharmony_ci len = scnprintf(buf, sizeof(buf), "%u\n", 24062306a36Sopenharmony_ci key->u.aes_cmac.replays); 24162306a36Sopenharmony_ci break; 24262306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_BIP_GMAC_128: 24362306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_BIP_GMAC_256: 24462306a36Sopenharmony_ci len = scnprintf(buf, sizeof(buf), "%u\n", 24562306a36Sopenharmony_ci key->u.aes_gmac.replays); 24662306a36Sopenharmony_ci break; 24762306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_GCMP: 24862306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_GCMP_256: 24962306a36Sopenharmony_ci len = scnprintf(buf, sizeof(buf), "%u\n", key->u.gcmp.replays); 25062306a36Sopenharmony_ci break; 25162306a36Sopenharmony_ci default: 25262306a36Sopenharmony_ci return 0; 25362306a36Sopenharmony_ci } 25462306a36Sopenharmony_ci return simple_read_from_buffer(userbuf, count, ppos, buf, len); 25562306a36Sopenharmony_ci} 25662306a36Sopenharmony_ciKEY_OPS(replays); 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_cistatic ssize_t key_icverrors_read(struct file *file, char __user *userbuf, 25962306a36Sopenharmony_ci size_t count, loff_t *ppos) 26062306a36Sopenharmony_ci{ 26162306a36Sopenharmony_ci struct ieee80211_key *key = file->private_data; 26262306a36Sopenharmony_ci char buf[20]; 26362306a36Sopenharmony_ci int len; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci switch (key->conf.cipher) { 26662306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_AES_CMAC: 26762306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_BIP_CMAC_256: 26862306a36Sopenharmony_ci len = scnprintf(buf, sizeof(buf), "%u\n", 26962306a36Sopenharmony_ci key->u.aes_cmac.icverrors); 27062306a36Sopenharmony_ci break; 27162306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_BIP_GMAC_128: 27262306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_BIP_GMAC_256: 27362306a36Sopenharmony_ci len = scnprintf(buf, sizeof(buf), "%u\n", 27462306a36Sopenharmony_ci key->u.aes_gmac.icverrors); 27562306a36Sopenharmony_ci break; 27662306a36Sopenharmony_ci default: 27762306a36Sopenharmony_ci return 0; 27862306a36Sopenharmony_ci } 27962306a36Sopenharmony_ci return simple_read_from_buffer(userbuf, count, ppos, buf, len); 28062306a36Sopenharmony_ci} 28162306a36Sopenharmony_ciKEY_OPS(icverrors); 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_cistatic ssize_t key_mic_failures_read(struct file *file, char __user *userbuf, 28462306a36Sopenharmony_ci size_t count, loff_t *ppos) 28562306a36Sopenharmony_ci{ 28662306a36Sopenharmony_ci struct ieee80211_key *key = file->private_data; 28762306a36Sopenharmony_ci char buf[20]; 28862306a36Sopenharmony_ci int len; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci if (key->conf.cipher != WLAN_CIPHER_SUITE_TKIP) 29162306a36Sopenharmony_ci return -EINVAL; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci len = scnprintf(buf, sizeof(buf), "%u\n", key->u.tkip.mic_failures); 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci return simple_read_from_buffer(userbuf, count, ppos, buf, len); 29662306a36Sopenharmony_ci} 29762306a36Sopenharmony_ciKEY_OPS(mic_failures); 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_cistatic ssize_t key_key_read(struct file *file, char __user *userbuf, 30062306a36Sopenharmony_ci size_t count, loff_t *ppos) 30162306a36Sopenharmony_ci{ 30262306a36Sopenharmony_ci struct ieee80211_key *key = file->private_data; 30362306a36Sopenharmony_ci int i, bufsize = 2 * key->conf.keylen + 2; 30462306a36Sopenharmony_ci char *buf = kmalloc(bufsize, GFP_KERNEL); 30562306a36Sopenharmony_ci char *p = buf; 30662306a36Sopenharmony_ci ssize_t res; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci if (!buf) 30962306a36Sopenharmony_ci return -ENOMEM; 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci for (i = 0; i < key->conf.keylen; i++) 31262306a36Sopenharmony_ci p += scnprintf(p, bufsize + buf - p, "%02x", key->conf.key[i]); 31362306a36Sopenharmony_ci p += scnprintf(p, bufsize+buf-p, "\n"); 31462306a36Sopenharmony_ci res = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); 31562306a36Sopenharmony_ci kfree(buf); 31662306a36Sopenharmony_ci return res; 31762306a36Sopenharmony_ci} 31862306a36Sopenharmony_ciKEY_OPS(key); 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci#define DEBUGFS_ADD(name) \ 32162306a36Sopenharmony_ci debugfs_create_file(#name, 0400, key->debugfs.dir, \ 32262306a36Sopenharmony_ci key, &key_##name##_ops) 32362306a36Sopenharmony_ci#define DEBUGFS_ADD_W(name) \ 32462306a36Sopenharmony_ci debugfs_create_file(#name, 0600, key->debugfs.dir, \ 32562306a36Sopenharmony_ci key, &key_##name##_ops); 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_civoid ieee80211_debugfs_key_add(struct ieee80211_key *key) 32862306a36Sopenharmony_ci{ 32962306a36Sopenharmony_ci static int keycount; 33062306a36Sopenharmony_ci char buf[100]; 33162306a36Sopenharmony_ci struct sta_info *sta; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci if (!key->local->debugfs.keys) 33462306a36Sopenharmony_ci return; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci sprintf(buf, "%d", keycount); 33762306a36Sopenharmony_ci key->debugfs.cnt = keycount; 33862306a36Sopenharmony_ci keycount++; 33962306a36Sopenharmony_ci key->debugfs.dir = debugfs_create_dir(buf, 34062306a36Sopenharmony_ci key->local->debugfs.keys); 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci sta = key->sta; 34362306a36Sopenharmony_ci if (sta) { 34462306a36Sopenharmony_ci sprintf(buf, "../../netdev:%s/stations/%pM", 34562306a36Sopenharmony_ci sta->sdata->name, sta->sta.addr); 34662306a36Sopenharmony_ci key->debugfs.stalink = 34762306a36Sopenharmony_ci debugfs_create_symlink("station", key->debugfs.dir, buf); 34862306a36Sopenharmony_ci } 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci DEBUGFS_ADD(keylen); 35162306a36Sopenharmony_ci DEBUGFS_ADD(flags); 35262306a36Sopenharmony_ci DEBUGFS_ADD(keyidx); 35362306a36Sopenharmony_ci DEBUGFS_ADD(hw_key_idx); 35462306a36Sopenharmony_ci DEBUGFS_ADD(algorithm); 35562306a36Sopenharmony_ci DEBUGFS_ADD_W(tx_spec); 35662306a36Sopenharmony_ci DEBUGFS_ADD(rx_spec); 35762306a36Sopenharmony_ci DEBUGFS_ADD(replays); 35862306a36Sopenharmony_ci DEBUGFS_ADD(icverrors); 35962306a36Sopenharmony_ci DEBUGFS_ADD(mic_failures); 36062306a36Sopenharmony_ci DEBUGFS_ADD(key); 36162306a36Sopenharmony_ci DEBUGFS_ADD(ifindex); 36262306a36Sopenharmony_ci}; 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_civoid ieee80211_debugfs_key_remove(struct ieee80211_key *key) 36562306a36Sopenharmony_ci{ 36662306a36Sopenharmony_ci if (!key) 36762306a36Sopenharmony_ci return; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci debugfs_remove_recursive(key->debugfs.dir); 37062306a36Sopenharmony_ci key->debugfs.dir = NULL; 37162306a36Sopenharmony_ci} 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_civoid ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) 37462306a36Sopenharmony_ci{ 37562306a36Sopenharmony_ci char buf[50]; 37662306a36Sopenharmony_ci struct ieee80211_key *key; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci if (!sdata->vif.debugfs_dir) 37962306a36Sopenharmony_ci return; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci lockdep_assert_held(&sdata->local->key_mtx); 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci debugfs_remove(sdata->debugfs.default_unicast_key); 38462306a36Sopenharmony_ci sdata->debugfs.default_unicast_key = NULL; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci if (sdata->default_unicast_key) { 38762306a36Sopenharmony_ci key = key_mtx_dereference(sdata->local, 38862306a36Sopenharmony_ci sdata->default_unicast_key); 38962306a36Sopenharmony_ci sprintf(buf, "../keys/%d", key->debugfs.cnt); 39062306a36Sopenharmony_ci sdata->debugfs.default_unicast_key = 39162306a36Sopenharmony_ci debugfs_create_symlink("default_unicast_key", 39262306a36Sopenharmony_ci sdata->vif.debugfs_dir, buf); 39362306a36Sopenharmony_ci } 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci debugfs_remove(sdata->debugfs.default_multicast_key); 39662306a36Sopenharmony_ci sdata->debugfs.default_multicast_key = NULL; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci if (sdata->deflink.default_multicast_key) { 39962306a36Sopenharmony_ci key = key_mtx_dereference(sdata->local, 40062306a36Sopenharmony_ci sdata->deflink.default_multicast_key); 40162306a36Sopenharmony_ci sprintf(buf, "../keys/%d", key->debugfs.cnt); 40262306a36Sopenharmony_ci sdata->debugfs.default_multicast_key = 40362306a36Sopenharmony_ci debugfs_create_symlink("default_multicast_key", 40462306a36Sopenharmony_ci sdata->vif.debugfs_dir, buf); 40562306a36Sopenharmony_ci } 40662306a36Sopenharmony_ci} 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_civoid ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) 40962306a36Sopenharmony_ci{ 41062306a36Sopenharmony_ci char buf[50]; 41162306a36Sopenharmony_ci struct ieee80211_key *key; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci if (!sdata->vif.debugfs_dir) 41462306a36Sopenharmony_ci return; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci key = key_mtx_dereference(sdata->local, 41762306a36Sopenharmony_ci sdata->deflink.default_mgmt_key); 41862306a36Sopenharmony_ci if (key) { 41962306a36Sopenharmony_ci sprintf(buf, "../keys/%d", key->debugfs.cnt); 42062306a36Sopenharmony_ci sdata->debugfs.default_mgmt_key = 42162306a36Sopenharmony_ci debugfs_create_symlink("default_mgmt_key", 42262306a36Sopenharmony_ci sdata->vif.debugfs_dir, buf); 42362306a36Sopenharmony_ci } else 42462306a36Sopenharmony_ci ieee80211_debugfs_key_remove_mgmt_default(sdata); 42562306a36Sopenharmony_ci} 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_civoid ieee80211_debugfs_key_remove_mgmt_default(struct ieee80211_sub_if_data *sdata) 42862306a36Sopenharmony_ci{ 42962306a36Sopenharmony_ci if (!sdata) 43062306a36Sopenharmony_ci return; 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci debugfs_remove(sdata->debugfs.default_mgmt_key); 43362306a36Sopenharmony_ci sdata->debugfs.default_mgmt_key = NULL; 43462306a36Sopenharmony_ci} 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_civoid 43762306a36Sopenharmony_ciieee80211_debugfs_key_add_beacon_default(struct ieee80211_sub_if_data *sdata) 43862306a36Sopenharmony_ci{ 43962306a36Sopenharmony_ci char buf[50]; 44062306a36Sopenharmony_ci struct ieee80211_key *key; 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci if (!sdata->vif.debugfs_dir) 44362306a36Sopenharmony_ci return; 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci key = key_mtx_dereference(sdata->local, 44662306a36Sopenharmony_ci sdata->deflink.default_beacon_key); 44762306a36Sopenharmony_ci if (key) { 44862306a36Sopenharmony_ci sprintf(buf, "../keys/%d", key->debugfs.cnt); 44962306a36Sopenharmony_ci sdata->debugfs.default_beacon_key = 45062306a36Sopenharmony_ci debugfs_create_symlink("default_beacon_key", 45162306a36Sopenharmony_ci sdata->vif.debugfs_dir, buf); 45262306a36Sopenharmony_ci } else { 45362306a36Sopenharmony_ci ieee80211_debugfs_key_remove_beacon_default(sdata); 45462306a36Sopenharmony_ci } 45562306a36Sopenharmony_ci} 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_civoid 45862306a36Sopenharmony_ciieee80211_debugfs_key_remove_beacon_default(struct ieee80211_sub_if_data *sdata) 45962306a36Sopenharmony_ci{ 46062306a36Sopenharmony_ci if (!sdata) 46162306a36Sopenharmony_ci return; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci debugfs_remove(sdata->debugfs.default_beacon_key); 46462306a36Sopenharmony_ci sdata->debugfs.default_beacon_key = NULL; 46562306a36Sopenharmony_ci} 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_civoid ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, 46862306a36Sopenharmony_ci struct sta_info *sta) 46962306a36Sopenharmony_ci{ 47062306a36Sopenharmony_ci debugfs_remove(key->debugfs.stalink); 47162306a36Sopenharmony_ci key->debugfs.stalink = NULL; 47262306a36Sopenharmony_ci} 473