cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

debugfs_key.c (12621B)


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