Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright 2003-2005  Devicescape Software, Inc.
0004  * Copyright (c) 2006   Jiri Benc <jbenc@suse.cz>
0005  * Copyright 2007   Johannes Berg <johannes@sipsolutions.net>
0006  * Copyright (C) 2015   Intel Deutschland GmbH
0007  * Copyright (C) 2021-2022   Intel Corporation
0008  */
0009 
0010 #include <linux/kobject.h>
0011 #include <linux/slab.h>
0012 #include "ieee80211_i.h"
0013 #include "key.h"
0014 #include "debugfs.h"
0015 #include "debugfs_key.h"
0016 
0017 #define KEY_READ(name, prop, format_string)             \
0018 static ssize_t key_##name##_read(struct file *file,         \
0019                  char __user *userbuf,          \
0020                  size_t count, loff_t *ppos)        \
0021 {                                   \
0022     struct ieee80211_key *key = file->private_data;         \
0023     return mac80211_format_buffer(userbuf, count, ppos,         \
0024                       format_string, key->prop);    \
0025 }
0026 #define KEY_READ_X(name) KEY_READ(name, name, "0x%x\n")
0027 
0028 #define KEY_OPS(name)                           \
0029 static const struct file_operations key_ ##name## _ops = {      \
0030     .read = key_##name##_read,                  \
0031     .open = simple_open,                        \
0032     .llseek = generic_file_llseek,                  \
0033 }
0034 
0035 #define KEY_OPS_W(name)                         \
0036 static const struct file_operations key_ ##name## _ops = {      \
0037     .read = key_##name##_read,                  \
0038     .write = key_##name##_write,                    \
0039     .open = simple_open,                        \
0040     .llseek = generic_file_llseek,                  \
0041 }
0042 
0043 #define KEY_FILE(name, format)                      \
0044          KEY_READ_##format(name)                \
0045          KEY_OPS(name)
0046 
0047 #define KEY_CONF_READ(name, format_string)              \
0048     KEY_READ(conf_##name, conf.name, format_string)
0049 #define KEY_CONF_READ_D(name) KEY_CONF_READ(name, "%d\n")
0050 
0051 #define KEY_CONF_OPS(name)                      \
0052 static const struct file_operations key_ ##name## _ops = {      \
0053     .read = key_conf_##name##_read,                 \
0054     .open = simple_open,                        \
0055     .llseek = generic_file_llseek,                  \
0056 }
0057 
0058 #define KEY_CONF_FILE(name, format)                 \
0059          KEY_CONF_READ_##format(name)               \
0060          KEY_CONF_OPS(name)
0061 
0062 KEY_CONF_FILE(keylen, D);
0063 KEY_CONF_FILE(keyidx, D);
0064 KEY_CONF_FILE(hw_key_idx, D);
0065 KEY_FILE(flags, X);
0066 KEY_READ(ifindex, sdata->name, "%s\n");
0067 KEY_OPS(ifindex);
0068 
0069 static ssize_t key_algorithm_read(struct file *file,
0070                   char __user *userbuf,
0071                   size_t count, loff_t *ppos)
0072 {
0073     char buf[15];
0074     struct ieee80211_key *key = file->private_data;
0075     u32 c = key->conf.cipher;
0076 
0077     sprintf(buf, "%.2x-%.2x-%.2x:%d\n",
0078         c >> 24, (c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff);
0079     return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
0080 }
0081 KEY_OPS(algorithm);
0082 
0083 static ssize_t key_tx_spec_write(struct file *file, const char __user *userbuf,
0084                  size_t count, loff_t *ppos)
0085 {
0086     struct ieee80211_key *key = file->private_data;
0087     u64 pn;
0088     int ret;
0089 
0090     switch (key->conf.cipher) {
0091     case WLAN_CIPHER_SUITE_WEP40:
0092     case WLAN_CIPHER_SUITE_WEP104:
0093         return -EINVAL;
0094     case WLAN_CIPHER_SUITE_TKIP:
0095         /* not supported yet */
0096         return -EOPNOTSUPP;
0097     case WLAN_CIPHER_SUITE_CCMP:
0098     case WLAN_CIPHER_SUITE_CCMP_256:
0099     case WLAN_CIPHER_SUITE_AES_CMAC:
0100     case WLAN_CIPHER_SUITE_BIP_CMAC_256:
0101     case WLAN_CIPHER_SUITE_BIP_GMAC_128:
0102     case WLAN_CIPHER_SUITE_BIP_GMAC_256:
0103     case WLAN_CIPHER_SUITE_GCMP:
0104     case WLAN_CIPHER_SUITE_GCMP_256:
0105         ret = kstrtou64_from_user(userbuf, count, 16, &pn);
0106         if (ret)
0107             return ret;
0108         /* PN is a 48-bit counter */
0109         if (pn >= (1ULL << 48))
0110             return -ERANGE;
0111         atomic64_set(&key->conf.tx_pn, pn);
0112         return count;
0113     default:
0114         return 0;
0115     }
0116 }
0117 
0118 static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
0119                 size_t count, loff_t *ppos)
0120 {
0121     u64 pn;
0122     char buf[20];
0123     int len;
0124     struct ieee80211_key *key = file->private_data;
0125 
0126     switch (key->conf.cipher) {
0127     case WLAN_CIPHER_SUITE_WEP40:
0128     case WLAN_CIPHER_SUITE_WEP104:
0129         len = scnprintf(buf, sizeof(buf), "\n");
0130         break;
0131     case WLAN_CIPHER_SUITE_TKIP:
0132         pn = atomic64_read(&key->conf.tx_pn);
0133         len = scnprintf(buf, sizeof(buf), "%08x %04x\n",
0134                 TKIP_PN_TO_IV32(pn),
0135                 TKIP_PN_TO_IV16(pn));
0136         break;
0137     case WLAN_CIPHER_SUITE_CCMP:
0138     case WLAN_CIPHER_SUITE_CCMP_256:
0139     case WLAN_CIPHER_SUITE_AES_CMAC:
0140     case WLAN_CIPHER_SUITE_BIP_CMAC_256:
0141     case WLAN_CIPHER_SUITE_BIP_GMAC_128:
0142     case WLAN_CIPHER_SUITE_BIP_GMAC_256:
0143     case WLAN_CIPHER_SUITE_GCMP:
0144     case WLAN_CIPHER_SUITE_GCMP_256:
0145         pn = atomic64_read(&key->conf.tx_pn);
0146         len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
0147                 (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
0148                 (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
0149         break;
0150     default:
0151         return 0;
0152     }
0153     return simple_read_from_buffer(userbuf, count, ppos, buf, len);
0154 }
0155 KEY_OPS_W(tx_spec);
0156 
0157 static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
0158                 size_t count, loff_t *ppos)
0159 {
0160     struct ieee80211_key *key = file->private_data;
0161     char buf[14*IEEE80211_NUM_TIDS+1], *p = buf;
0162     int i, len;
0163     const u8 *rpn;
0164 
0165     switch (key->conf.cipher) {
0166     case WLAN_CIPHER_SUITE_WEP40:
0167     case WLAN_CIPHER_SUITE_WEP104:
0168         len = scnprintf(buf, sizeof(buf), "\n");
0169         break;
0170     case WLAN_CIPHER_SUITE_TKIP:
0171         for (i = 0; i < IEEE80211_NUM_TIDS; i++)
0172             p += scnprintf(p, sizeof(buf)+buf-p,
0173                        "%08x %04x\n",
0174                        key->u.tkip.rx[i].iv32,
0175                        key->u.tkip.rx[i].iv16);
0176         len = p - buf;
0177         break;
0178     case WLAN_CIPHER_SUITE_CCMP:
0179     case WLAN_CIPHER_SUITE_CCMP_256:
0180         for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) {
0181             rpn = key->u.ccmp.rx_pn[i];
0182             p += scnprintf(p, sizeof(buf)+buf-p,
0183                        "%02x%02x%02x%02x%02x%02x\n",
0184                        rpn[0], rpn[1], rpn[2],
0185                        rpn[3], rpn[4], rpn[5]);
0186         }
0187         len = p - buf;
0188         break;
0189     case WLAN_CIPHER_SUITE_AES_CMAC:
0190     case WLAN_CIPHER_SUITE_BIP_CMAC_256:
0191         rpn = key->u.aes_cmac.rx_pn;
0192         p += scnprintf(p, sizeof(buf)+buf-p,
0193                    "%02x%02x%02x%02x%02x%02x\n",
0194                    rpn[0], rpn[1], rpn[2],
0195                    rpn[3], rpn[4], rpn[5]);
0196         len = p - buf;
0197         break;
0198     case WLAN_CIPHER_SUITE_BIP_GMAC_128:
0199     case WLAN_CIPHER_SUITE_BIP_GMAC_256:
0200         rpn = key->u.aes_gmac.rx_pn;
0201         p += scnprintf(p, sizeof(buf)+buf-p,
0202                    "%02x%02x%02x%02x%02x%02x\n",
0203                    rpn[0], rpn[1], rpn[2],
0204                    rpn[3], rpn[4], rpn[5]);
0205         len = p - buf;
0206         break;
0207     case WLAN_CIPHER_SUITE_GCMP:
0208     case WLAN_CIPHER_SUITE_GCMP_256:
0209         for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) {
0210             rpn = key->u.gcmp.rx_pn[i];
0211             p += scnprintf(p, sizeof(buf)+buf-p,
0212                        "%02x%02x%02x%02x%02x%02x\n",
0213                        rpn[0], rpn[1], rpn[2],
0214                        rpn[3], rpn[4], rpn[5]);
0215         }
0216         len = p - buf;
0217         break;
0218     default:
0219         return 0;
0220     }
0221     return simple_read_from_buffer(userbuf, count, ppos, buf, len);
0222 }
0223 KEY_OPS(rx_spec);
0224 
0225 static ssize_t key_replays_read(struct file *file, char __user *userbuf,
0226                 size_t count, loff_t *ppos)
0227 {
0228     struct ieee80211_key *key = file->private_data;
0229     char buf[20];
0230     int len;
0231 
0232     switch (key->conf.cipher) {
0233     case WLAN_CIPHER_SUITE_CCMP:
0234     case WLAN_CIPHER_SUITE_CCMP_256:
0235         len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays);
0236         break;
0237     case WLAN_CIPHER_SUITE_AES_CMAC:
0238     case WLAN_CIPHER_SUITE_BIP_CMAC_256:
0239         len = scnprintf(buf, sizeof(buf), "%u\n",
0240                 key->u.aes_cmac.replays);
0241         break;
0242     case WLAN_CIPHER_SUITE_BIP_GMAC_128:
0243     case WLAN_CIPHER_SUITE_BIP_GMAC_256:
0244         len = scnprintf(buf, sizeof(buf), "%u\n",
0245                 key->u.aes_gmac.replays);
0246         break;
0247     case WLAN_CIPHER_SUITE_GCMP:
0248     case WLAN_CIPHER_SUITE_GCMP_256:
0249         len = scnprintf(buf, sizeof(buf), "%u\n", key->u.gcmp.replays);
0250         break;
0251     default:
0252         return 0;
0253     }
0254     return simple_read_from_buffer(userbuf, count, ppos, buf, len);
0255 }
0256 KEY_OPS(replays);
0257 
0258 static ssize_t key_icverrors_read(struct file *file, char __user *userbuf,
0259                   size_t count, loff_t *ppos)
0260 {
0261     struct ieee80211_key *key = file->private_data;
0262     char buf[20];
0263     int len;
0264 
0265     switch (key->conf.cipher) {
0266     case WLAN_CIPHER_SUITE_AES_CMAC:
0267     case WLAN_CIPHER_SUITE_BIP_CMAC_256:
0268         len = scnprintf(buf, sizeof(buf), "%u\n",
0269                 key->u.aes_cmac.icverrors);
0270         break;
0271     case WLAN_CIPHER_SUITE_BIP_GMAC_128:
0272     case WLAN_CIPHER_SUITE_BIP_GMAC_256:
0273         len = scnprintf(buf, sizeof(buf), "%u\n",
0274                 key->u.aes_gmac.icverrors);
0275         break;
0276     default:
0277         return 0;
0278     }
0279     return simple_read_from_buffer(userbuf, count, ppos, buf, len);
0280 }
0281 KEY_OPS(icverrors);
0282 
0283 static ssize_t key_mic_failures_read(struct file *file, char __user *userbuf,
0284                      size_t count, loff_t *ppos)
0285 {
0286     struct ieee80211_key *key = file->private_data;
0287     char buf[20];
0288     int len;
0289 
0290     if (key->conf.cipher != WLAN_CIPHER_SUITE_TKIP)
0291         return -EINVAL;
0292 
0293     len = scnprintf(buf, sizeof(buf), "%u\n", key->u.tkip.mic_failures);
0294 
0295     return simple_read_from_buffer(userbuf, count, ppos, buf, len);
0296 }
0297 KEY_OPS(mic_failures);
0298 
0299 static ssize_t key_key_read(struct file *file, char __user *userbuf,
0300                 size_t count, loff_t *ppos)
0301 {
0302     struct ieee80211_key *key = file->private_data;
0303     int i, bufsize = 2 * key->conf.keylen + 2;
0304     char *buf = kmalloc(bufsize, GFP_KERNEL);
0305     char *p = buf;
0306     ssize_t res;
0307 
0308     if (!buf)
0309         return -ENOMEM;
0310 
0311     for (i = 0; i < key->conf.keylen; i++)
0312         p += scnprintf(p, bufsize + buf - p, "%02x", key->conf.key[i]);
0313     p += scnprintf(p, bufsize+buf-p, "\n");
0314     res = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
0315     kfree(buf);
0316     return res;
0317 }
0318 KEY_OPS(key);
0319 
0320 #define DEBUGFS_ADD(name) \
0321     debugfs_create_file(#name, 0400, key->debugfs.dir, \
0322                 key, &key_##name##_ops)
0323 #define DEBUGFS_ADD_W(name) \
0324     debugfs_create_file(#name, 0600, key->debugfs.dir, \
0325                 key, &key_##name##_ops);
0326 
0327 void ieee80211_debugfs_key_add(struct ieee80211_key *key)
0328 {
0329     static int keycount;
0330     char buf[100];
0331     struct sta_info *sta;
0332 
0333     if (!key->local->debugfs.keys)
0334         return;
0335 
0336     sprintf(buf, "%d", keycount);
0337     key->debugfs.cnt = keycount;
0338     keycount++;
0339     key->debugfs.dir = debugfs_create_dir(buf,
0340                     key->local->debugfs.keys);
0341 
0342     sta = key->sta;
0343     if (sta) {
0344         sprintf(buf, "../../netdev:%s/stations/%pM",
0345             sta->sdata->name, sta->sta.addr);
0346         key->debugfs.stalink =
0347             debugfs_create_symlink("station", key->debugfs.dir, buf);
0348     }
0349 
0350     DEBUGFS_ADD(keylen);
0351     DEBUGFS_ADD(flags);
0352     DEBUGFS_ADD(keyidx);
0353     DEBUGFS_ADD(hw_key_idx);
0354     DEBUGFS_ADD(algorithm);
0355     DEBUGFS_ADD_W(tx_spec);
0356     DEBUGFS_ADD(rx_spec);
0357     DEBUGFS_ADD(replays);
0358     DEBUGFS_ADD(icverrors);
0359     DEBUGFS_ADD(mic_failures);
0360     DEBUGFS_ADD(key);
0361     DEBUGFS_ADD(ifindex);
0362 };
0363 
0364 void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
0365 {
0366     if (!key)
0367         return;
0368 
0369     debugfs_remove_recursive(key->debugfs.dir);
0370     key->debugfs.dir = NULL;
0371 }
0372 
0373 void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata)
0374 {
0375     char buf[50];
0376     struct ieee80211_key *key;
0377 
0378     if (!sdata->vif.debugfs_dir)
0379         return;
0380 
0381     lockdep_assert_held(&sdata->local->key_mtx);
0382 
0383     debugfs_remove(sdata->debugfs.default_unicast_key);
0384     sdata->debugfs.default_unicast_key = NULL;
0385 
0386     if (sdata->default_unicast_key) {
0387         key = key_mtx_dereference(sdata->local,
0388                       sdata->default_unicast_key);
0389         sprintf(buf, "../keys/%d", key->debugfs.cnt);
0390         sdata->debugfs.default_unicast_key =
0391             debugfs_create_symlink("default_unicast_key",
0392                            sdata->vif.debugfs_dir, buf);
0393     }
0394 
0395     debugfs_remove(sdata->debugfs.default_multicast_key);
0396     sdata->debugfs.default_multicast_key = NULL;
0397 
0398     if (sdata->deflink.default_multicast_key) {
0399         key = key_mtx_dereference(sdata->local,
0400                       sdata->deflink.default_multicast_key);
0401         sprintf(buf, "../keys/%d", key->debugfs.cnt);
0402         sdata->debugfs.default_multicast_key =
0403             debugfs_create_symlink("default_multicast_key",
0404                            sdata->vif.debugfs_dir, buf);
0405     }
0406 }
0407 
0408 void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata)
0409 {
0410     char buf[50];
0411     struct ieee80211_key *key;
0412 
0413     if (!sdata->vif.debugfs_dir)
0414         return;
0415 
0416     key = key_mtx_dereference(sdata->local,
0417                   sdata->deflink.default_mgmt_key);
0418     if (key) {
0419         sprintf(buf, "../keys/%d", key->debugfs.cnt);
0420         sdata->debugfs.default_mgmt_key =
0421             debugfs_create_symlink("default_mgmt_key",
0422                            sdata->vif.debugfs_dir, buf);
0423     } else
0424         ieee80211_debugfs_key_remove_mgmt_default(sdata);
0425 }
0426 
0427 void ieee80211_debugfs_key_remove_mgmt_default(struct ieee80211_sub_if_data *sdata)
0428 {
0429     if (!sdata)
0430         return;
0431 
0432     debugfs_remove(sdata->debugfs.default_mgmt_key);
0433     sdata->debugfs.default_mgmt_key = NULL;
0434 }
0435 
0436 void
0437 ieee80211_debugfs_key_add_beacon_default(struct ieee80211_sub_if_data *sdata)
0438 {
0439     char buf[50];
0440     struct ieee80211_key *key;
0441 
0442     if (!sdata->vif.debugfs_dir)
0443         return;
0444 
0445     key = key_mtx_dereference(sdata->local,
0446                   sdata->deflink.default_beacon_key);
0447     if (key) {
0448         sprintf(buf, "../keys/%d", key->debugfs.cnt);
0449         sdata->debugfs.default_beacon_key =
0450             debugfs_create_symlink("default_beacon_key",
0451                            sdata->vif.debugfs_dir, buf);
0452     } else {
0453         ieee80211_debugfs_key_remove_beacon_default(sdata);
0454     }
0455 }
0456 
0457 void
0458 ieee80211_debugfs_key_remove_beacon_default(struct ieee80211_sub_if_data *sdata)
0459 {
0460     if (!sdata)
0461         return;
0462 
0463     debugfs_remove(sdata->debugfs.default_beacon_key);
0464     sdata->debugfs.default_beacon_key = NULL;
0465 }
0466 
0467 void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
0468                    struct sta_info *sta)
0469 {
0470     debugfs_remove(key->debugfs.stalink);
0471     key->debugfs.stalink = NULL;
0472 }