1e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc/* 2e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc * Copyright 2003-2005 Devicescape Software, Inc. 3e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> 4e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> 5e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc * 6e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc * This program is free software; you can redistribute it and/or modify 7e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc * it under the terms of the GNU General Public License version 2 as 8e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc * published by the Free Software Foundation. 9e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc */ 10e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 11e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc#include <linux/kobject.h> 125a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 13e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc#include "ieee80211_i.h" 142c8dccc77420fb7433da5674818959d3499d35beJohannes Berg#include "key.h" 15e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc#include "debugfs.h" 16e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc#include "debugfs_key.h" 17e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 1807caf9d6c9135ae25a760867f37aab90c1008380Eliad Peller#define KEY_READ(name, prop, format_string) \ 19e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Bencstatic ssize_t key_##name##_read(struct file *file, \ 20e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc char __user *userbuf, \ 21e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc size_t count, loff_t *ppos) \ 22e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc{ \ 23e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc struct ieee80211_key *key = file->private_data; \ 2407caf9d6c9135ae25a760867f37aab90c1008380Eliad Peller return mac80211_format_buffer(userbuf, count, ppos, \ 2507caf9d6c9135ae25a760867f37aab90c1008380Eliad Peller format_string, key->prop); \ 26e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc} 2707caf9d6c9135ae25a760867f37aab90c1008380Eliad Peller#define KEY_READ_D(name) KEY_READ(name, name, "%d\n") 2807caf9d6c9135ae25a760867f37aab90c1008380Eliad Peller#define KEY_READ_X(name) KEY_READ(name, name, "0x%x\n") 29e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 30e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc#define KEY_OPS(name) \ 31e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Bencstatic const struct file_operations key_ ##name## _ops = { \ 32e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc .read = key_##name##_read, \ 33234e340582901211f40d8c732afc49f0630ecf05Stephen Boyd .open = simple_open, \ 342b18ab36cf7e956fb5b5ee12847e94fc66d496f4Arnd Bergmann .llseek = generic_file_llseek, \ 35e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc} 36e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 37e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc#define KEY_FILE(name, format) \ 38e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc KEY_READ_##format(name) \ 39e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc KEY_OPS(name) 40e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 4107caf9d6c9135ae25a760867f37aab90c1008380Eliad Peller#define KEY_CONF_READ(name, format_string) \ 4207caf9d6c9135ae25a760867f37aab90c1008380Eliad Peller KEY_READ(conf_##name, conf.name, format_string) 4307caf9d6c9135ae25a760867f37aab90c1008380Eliad Peller#define KEY_CONF_READ_D(name) KEY_CONF_READ(name, "%d\n") 448f20fc24986a083228823d9b68adca20714b254eJohannes Berg 458f20fc24986a083228823d9b68adca20714b254eJohannes Berg#define KEY_CONF_OPS(name) \ 468f20fc24986a083228823d9b68adca20714b254eJohannes Bergstatic const struct file_operations key_ ##name## _ops = { \ 478f20fc24986a083228823d9b68adca20714b254eJohannes Berg .read = key_conf_##name##_read, \ 48234e340582901211f40d8c732afc49f0630ecf05Stephen Boyd .open = simple_open, \ 492b18ab36cf7e956fb5b5ee12847e94fc66d496f4Arnd Bergmann .llseek = generic_file_llseek, \ 508f20fc24986a083228823d9b68adca20714b254eJohannes Berg} 518f20fc24986a083228823d9b68adca20714b254eJohannes Berg 528f20fc24986a083228823d9b68adca20714b254eJohannes Berg#define KEY_CONF_FILE(name, format) \ 538f20fc24986a083228823d9b68adca20714b254eJohannes Berg KEY_CONF_READ_##format(name) \ 548f20fc24986a083228823d9b68adca20714b254eJohannes Berg KEY_CONF_OPS(name) 558f20fc24986a083228823d9b68adca20714b254eJohannes Berg 568f20fc24986a083228823d9b68adca20714b254eJohannes BergKEY_CONF_FILE(keylen, D); 578f20fc24986a083228823d9b68adca20714b254eJohannes BergKEY_CONF_FILE(keyidx, D); 588f20fc24986a083228823d9b68adca20714b254eJohannes BergKEY_CONF_FILE(hw_key_idx, D); 5911a843b7e16062389c53ba393c7913956e034eb2Johannes BergKEY_FILE(flags, X); 60e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri BencKEY_FILE(tx_rx_count, D); 6107caf9d6c9135ae25a760867f37aab90c1008380Eliad PellerKEY_READ(ifindex, sdata->name, "%s\n"); 62e7a64f12a452d39ab50e5580e93bc48b3b15f30cJohannes BergKEY_OPS(ifindex); 63e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 64e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Bencstatic ssize_t key_algorithm_read(struct file *file, 65e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc char __user *userbuf, 66e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc size_t count, loff_t *ppos) 67e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc{ 6897359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg char buf[15]; 69e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc struct ieee80211_key *key = file->private_data; 7097359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg u32 c = key->conf.cipher; 71e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 7297359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg sprintf(buf, "%.2x-%.2x-%.2x:%d\n", 7397359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg c >> 24, (c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff); 7497359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf)); 75e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc} 76e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri BencKEY_OPS(algorithm); 77e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 78e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Bencstatic ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, 79e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc size_t count, loff_t *ppos) 80e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc{ 81aba83a0b301c32dbb91c017f33307611e1a1d384Johannes Berg u64 pn; 82e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc char buf[20]; 83e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc int len; 84e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc struct ieee80211_key *key = file->private_data; 85e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 8697359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg switch (key->conf.cipher) { 8797359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg case WLAN_CIPHER_SUITE_WEP40: 8897359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg case WLAN_CIPHER_SUITE_WEP104: 89e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc len = scnprintf(buf, sizeof(buf), "\n"); 9050339a67e2d4386d8919195989371579cab8649dJohannes Berg break; 9197359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg case WLAN_CIPHER_SUITE_TKIP: 92e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc len = scnprintf(buf, sizeof(buf), "%08x %04x\n", 93b0f76b335f8b1c324b4b2be06369d391b26a7cc9Harvey Harrison key->u.tkip.tx.iv32, 94b0f76b335f8b1c324b4b2be06369d391b26a7cc9Harvey Harrison key->u.tkip.tx.iv16); 9550339a67e2d4386d8919195989371579cab8649dJohannes Berg break; 9697359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg case WLAN_CIPHER_SUITE_CCMP: 97aba83a0b301c32dbb91c017f33307611e1a1d384Johannes Berg pn = atomic64_read(&key->u.ccmp.tx_pn); 98e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", 99aba83a0b301c32dbb91c017f33307611e1a1d384Johannes Berg (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), 100aba83a0b301c32dbb91c017f33307611e1a1d384Johannes Berg (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); 10150339a67e2d4386d8919195989371579cab8649dJohannes Berg break; 10297359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg case WLAN_CIPHER_SUITE_AES_CMAC: 10375396ae6d433b49482e377e6f8dbf1f42ad53f3aJohannes Berg pn = atomic64_read(&key->u.aes_cmac.tx_pn); 1043cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", 10575396ae6d433b49482e377e6f8dbf1f42ad53f3aJohannes Berg (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), 10675396ae6d433b49482e377e6f8dbf1f42ad53f3aJohannes Berg (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); 1073cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen break; 108e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc default: 109e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc return 0; 110e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc } 111e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc return simple_read_from_buffer(userbuf, count, ppos, buf, len); 112e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc} 113e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri BencKEY_OPS(tx_spec); 114e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 115e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Bencstatic ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, 116e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc size_t count, loff_t *ppos) 117e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc{ 118e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc struct ieee80211_key *key = file->private_data; 1195a306f5887d5fd840beb8ea872897fa89e8fcdefJohannes Berg char buf[14*IEEE80211_NUM_TIDS+1], *p = buf; 120e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc int i, len; 121e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc const u8 *rpn; 122e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 12397359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg switch (key->conf.cipher) { 12497359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg case WLAN_CIPHER_SUITE_WEP40: 12597359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg case WLAN_CIPHER_SUITE_WEP104: 126e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc len = scnprintf(buf, sizeof(buf), "\n"); 12750339a67e2d4386d8919195989371579cab8649dJohannes Berg break; 12897359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg case WLAN_CIPHER_SUITE_TKIP: 1295a306f5887d5fd840beb8ea872897fa89e8fcdefJohannes Berg for (i = 0; i < IEEE80211_NUM_TIDS; i++) 130e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc p += scnprintf(p, sizeof(buf)+buf-p, 131e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc "%08x %04x\n", 132b0f76b335f8b1c324b4b2be06369d391b26a7cc9Harvey Harrison key->u.tkip.rx[i].iv32, 133b0f76b335f8b1c324b4b2be06369d391b26a7cc9Harvey Harrison key->u.tkip.rx[i].iv16); 134e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc len = p - buf; 13550339a67e2d4386d8919195989371579cab8649dJohannes Berg break; 13697359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg case WLAN_CIPHER_SUITE_CCMP: 1375a306f5887d5fd840beb8ea872897fa89e8fcdefJohannes Berg for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) { 138e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc rpn = key->u.ccmp.rx_pn[i]; 139e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc p += scnprintf(p, sizeof(buf)+buf-p, 140e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc "%02x%02x%02x%02x%02x%02x\n", 141e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc rpn[0], rpn[1], rpn[2], 142e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc rpn[3], rpn[4], rpn[5]); 143e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc } 144e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc len = p - buf; 14550339a67e2d4386d8919195989371579cab8649dJohannes Berg break; 14697359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg case WLAN_CIPHER_SUITE_AES_CMAC: 1473cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen rpn = key->u.aes_cmac.rx_pn; 1483cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen p += scnprintf(p, sizeof(buf)+buf-p, 1493cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen "%02x%02x%02x%02x%02x%02x\n", 1503cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen rpn[0], rpn[1], rpn[2], 1513cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen rpn[3], rpn[4], rpn[5]); 1523cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen len = p - buf; 1533cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen break; 154e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc default: 155e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc return 0; 156e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc } 157e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc return simple_read_from_buffer(userbuf, count, ppos, buf, len); 158e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc} 159e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri BencKEY_OPS(rx_spec); 160e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 161e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Bencstatic ssize_t key_replays_read(struct file *file, char __user *userbuf, 162e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc size_t count, loff_t *ppos) 163e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc{ 164e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc struct ieee80211_key *key = file->private_data; 165e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc char buf[20]; 166e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc int len; 167e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 16897359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg switch (key->conf.cipher) { 16997359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg case WLAN_CIPHER_SUITE_CCMP: 1703cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays); 1713cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen break; 17297359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg case WLAN_CIPHER_SUITE_AES_CMAC: 1733cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen len = scnprintf(buf, sizeof(buf), "%u\n", 1743cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen key->u.aes_cmac.replays); 1753cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen break; 1763cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen default: 177e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc return 0; 1783cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen } 179e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc return simple_read_from_buffer(userbuf, count, ppos, buf, len); 180e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc} 181e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri BencKEY_OPS(replays); 182e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 1833cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinenstatic ssize_t key_icverrors_read(struct file *file, char __user *userbuf, 1843cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen size_t count, loff_t *ppos) 1853cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen{ 1863cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen struct ieee80211_key *key = file->private_data; 1873cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen char buf[20]; 1883cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen int len; 1893cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen 19097359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg switch (key->conf.cipher) { 19197359d1235eaf634fe706c9faa6e40181cc95fb8Johannes Berg case WLAN_CIPHER_SUITE_AES_CMAC: 1923cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen len = scnprintf(buf, sizeof(buf), "%u\n", 1933cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen key->u.aes_cmac.icverrors); 1943cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen break; 1953cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen default: 1963cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen return 0; 1973cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen } 1983cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen return simple_read_from_buffer(userbuf, count, ppos, buf, len); 1993cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen} 2003cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni MalinenKEY_OPS(icverrors); 2013cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen 202b98ea05861d76f458029096e8b2939fcb58e9530Saravanastatic ssize_t key_mic_failures_read(struct file *file, char __user *userbuf, 203b98ea05861d76f458029096e8b2939fcb58e9530Saravana size_t count, loff_t *ppos) 204b98ea05861d76f458029096e8b2939fcb58e9530Saravana{ 205b98ea05861d76f458029096e8b2939fcb58e9530Saravana struct ieee80211_key *key = file->private_data; 206b98ea05861d76f458029096e8b2939fcb58e9530Saravana char buf[20]; 207b98ea05861d76f458029096e8b2939fcb58e9530Saravana int len; 208b98ea05861d76f458029096e8b2939fcb58e9530Saravana 209b98ea05861d76f458029096e8b2939fcb58e9530Saravana if (key->conf.cipher != WLAN_CIPHER_SUITE_TKIP) 210b98ea05861d76f458029096e8b2939fcb58e9530Saravana return -EINVAL; 211b98ea05861d76f458029096e8b2939fcb58e9530Saravana 212b98ea05861d76f458029096e8b2939fcb58e9530Saravana len = scnprintf(buf, sizeof(buf), "%u\n", key->u.tkip.mic_failures); 213b98ea05861d76f458029096e8b2939fcb58e9530Saravana 214b98ea05861d76f458029096e8b2939fcb58e9530Saravana return simple_read_from_buffer(userbuf, count, ppos, buf, len); 215b98ea05861d76f458029096e8b2939fcb58e9530Saravana} 216b98ea05861d76f458029096e8b2939fcb58e9530SaravanaKEY_OPS(mic_failures); 217b98ea05861d76f458029096e8b2939fcb58e9530Saravana 218e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Bencstatic ssize_t key_key_read(struct file *file, char __user *userbuf, 219e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc size_t count, loff_t *ppos) 220e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc{ 221e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc struct ieee80211_key *key = file->private_data; 222520efd1ace3f826120482e57a95d649b4e1c1684Jesper Juhl int i, bufsize = 2 * key->conf.keylen + 2; 223e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc char *buf = kmalloc(bufsize, GFP_KERNEL); 224e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc char *p = buf; 225520efd1ace3f826120482e57a95d649b4e1c1684Jesper Juhl ssize_t res; 226520efd1ace3f826120482e57a95d649b4e1c1684Jesper Juhl 227520efd1ace3f826120482e57a95d649b4e1c1684Jesper Juhl if (!buf) 228520efd1ace3f826120482e57a95d649b4e1c1684Jesper Juhl return -ENOMEM; 229e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 2308f20fc24986a083228823d9b68adca20714b254eJohannes Berg for (i = 0; i < key->conf.keylen; i++) 2318f20fc24986a083228823d9b68adca20714b254eJohannes Berg p += scnprintf(p, bufsize + buf - p, "%02x", key->conf.key[i]); 232e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc p += scnprintf(p, bufsize+buf-p, "\n"); 233e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc res = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); 234e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc kfree(buf); 235e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc return res; 236e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc} 237e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri BencKEY_OPS(key); 238e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 239e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc#define DEBUGFS_ADD(name) \ 2407bcfaf2f431c09c51fe776fc06638b25d3b421c5Johannes Berg debugfs_create_file(#name, 0400, key->debugfs.dir, \ 2417bcfaf2f431c09c51fe776fc06638b25d3b421c5Johannes Berg key, &key_##name##_ops); 242e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 2433b96766f0e643f52ae19e134664df6730c737e87Johannes Bergvoid ieee80211_debugfs_key_add(struct ieee80211_key *key) 2449446f3efc53512e5ad9e0966539021a2a41fe5a0Johannes Berg{ 24550339a67e2d4386d8919195989371579cab8649dJohannes Berg static int keycount; 2469446f3efc53512e5ad9e0966539021a2a41fe5a0Johannes Berg char buf[100]; 2473b96766f0e643f52ae19e134664df6730c737e87Johannes Berg struct sta_info *sta; 248e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 2493b96766f0e643f52ae19e134664df6730c737e87Johannes Berg if (!key->local->debugfs.keys) 250e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc return; 251e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 25250339a67e2d4386d8919195989371579cab8649dJohannes Berg sprintf(buf, "%d", keycount); 253d9c58f30b08bfe1e689537af5bc855a76d0fae25Johannes Berg key->debugfs.cnt = keycount; 25450339a67e2d4386d8919195989371579cab8649dJohannes Berg keycount++; 255e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc key->debugfs.dir = debugfs_create_dir(buf, 2563b96766f0e643f52ae19e134664df6730c737e87Johannes Berg key->local->debugfs.keys); 257e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 258e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc if (!key->debugfs.dir) 259e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc return; 260e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 26140b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg sta = key->sta; 26240b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg if (sta) { 2639446f3efc53512e5ad9e0966539021a2a41fe5a0Johannes Berg sprintf(buf, "../../netdev:%s/stations/%pM", 2649446f3efc53512e5ad9e0966539021a2a41fe5a0Johannes Berg sta->sdata->name, sta->sta.addr); 2653b96766f0e643f52ae19e134664df6730c737e87Johannes Berg key->debugfs.stalink = 2663b96766f0e643f52ae19e134664df6730c737e87Johannes Berg debugfs_create_symlink("station", key->debugfs.dir, buf); 26740b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg } 2683b96766f0e643f52ae19e134664df6730c737e87Johannes Berg 269e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc DEBUGFS_ADD(keylen); 2708f20fc24986a083228823d9b68adca20714b254eJohannes Berg DEBUGFS_ADD(flags); 271e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc DEBUGFS_ADD(keyidx); 272e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc DEBUGFS_ADD(hw_key_idx); 273e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc DEBUGFS_ADD(tx_rx_count); 274e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc DEBUGFS_ADD(algorithm); 275e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc DEBUGFS_ADD(tx_spec); 276e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc DEBUGFS_ADD(rx_spec); 277e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc DEBUGFS_ADD(replays); 2783cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen DEBUGFS_ADD(icverrors); 279b98ea05861d76f458029096e8b2939fcb58e9530Saravana DEBUGFS_ADD(mic_failures); 280e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc DEBUGFS_ADD(key); 281e7a64f12a452d39ab50e5580e93bc48b3b15f30cJohannes Berg DEBUGFS_ADD(ifindex); 282e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc}; 283e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 284e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Bencvoid ieee80211_debugfs_key_remove(struct ieee80211_key *key) 285e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc{ 286e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc if (!key) 287e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc return; 288e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 2897bcfaf2f431c09c51fe776fc06638b25d3b421c5Johannes Berg debugfs_remove_recursive(key->debugfs.dir); 290e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc key->debugfs.dir = NULL; 291e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc} 292f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg 293f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Bergvoid ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) 294e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc{ 295e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc char buf[50]; 29678520cad4b222d81fa18f2dcfa52394d8d1722b0Johannes Berg struct ieee80211_key *key; 297e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 298ddbfe860acc39d4856a86186eb8a292426ea6224Stanislaw Gruszka if (!sdata->vif.debugfs_dir) 299e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc return; 300e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 301f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg lockdep_assert_held(&sdata->local->key_mtx); 30278520cad4b222d81fa18f2dcfa52394d8d1722b0Johannes Berg 303135792ec246ddd0b2738dd95447297ea0b91943bJohannes Berg if (sdata->debugfs.default_unicast_key) { 304135792ec246ddd0b2738dd95447297ea0b91943bJohannes Berg debugfs_remove(sdata->debugfs.default_unicast_key); 305135792ec246ddd0b2738dd95447297ea0b91943bJohannes Berg sdata->debugfs.default_unicast_key = NULL; 306135792ec246ddd0b2738dd95447297ea0b91943bJohannes Berg } 307135792ec246ddd0b2738dd95447297ea0b91943bJohannes Berg 308f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg if (sdata->default_unicast_key) { 30940b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg key = key_mtx_dereference(sdata->local, 31040b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg sdata->default_unicast_key); 31178520cad4b222d81fa18f2dcfa52394d8d1722b0Johannes Berg sprintf(buf, "../keys/%d", key->debugfs.cnt); 312f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg sdata->debugfs.default_unicast_key = 313f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg debugfs_create_symlink("default_unicast_key", 314ddbfe860acc39d4856a86186eb8a292426ea6224Stanislaw Gruszka sdata->vif.debugfs_dir, buf); 315135792ec246ddd0b2738dd95447297ea0b91943bJohannes Berg } 316135792ec246ddd0b2738dd95447297ea0b91943bJohannes Berg 317135792ec246ddd0b2738dd95447297ea0b91943bJohannes Berg if (sdata->debugfs.default_multicast_key) { 318135792ec246ddd0b2738dd95447297ea0b91943bJohannes Berg debugfs_remove(sdata->debugfs.default_multicast_key); 319135792ec246ddd0b2738dd95447297ea0b91943bJohannes Berg sdata->debugfs.default_multicast_key = NULL; 320f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg } 321e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 322f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg if (sdata->default_multicast_key) { 32340b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg key = key_mtx_dereference(sdata->local, 32440b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg sdata->default_multicast_key); 325f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg sprintf(buf, "../keys/%d", key->debugfs.cnt); 326f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg sdata->debugfs.default_multicast_key = 327f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg debugfs_create_symlink("default_multicast_key", 328ddbfe860acc39d4856a86186eb8a292426ea6224Stanislaw Gruszka sdata->vif.debugfs_dir, buf); 329f7e0104c1a4e77cc4f23d5969b0677bdc4f62c63Johannes Berg } 330e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc} 331e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc 3323cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinenvoid ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) 3333cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen{ 3343cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen char buf[50]; 3353cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen struct ieee80211_key *key; 3363cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen 337ddbfe860acc39d4856a86186eb8a292426ea6224Stanislaw Gruszka if (!sdata->vif.debugfs_dir) 3383cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen return; 3393cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen 34040b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg key = key_mtx_dereference(sdata->local, 34140b275b69ee660274b77fb612b0db31fd282fc3fJohannes Berg sdata->default_mgmt_key); 3423cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen if (key) { 3433cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen sprintf(buf, "../keys/%d", key->debugfs.cnt); 3447bcfaf2f431c09c51fe776fc06638b25d3b421c5Johannes Berg sdata->debugfs.default_mgmt_key = 3453cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen debugfs_create_symlink("default_mgmt_key", 346ddbfe860acc39d4856a86186eb8a292426ea6224Stanislaw Gruszka sdata->vif.debugfs_dir, buf); 3473cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen } else 3483cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen ieee80211_debugfs_key_remove_mgmt_default(sdata); 3493cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen} 3503cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen 3513cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinenvoid ieee80211_debugfs_key_remove_mgmt_default(struct ieee80211_sub_if_data *sdata) 3523cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen{ 3533cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen if (!sdata) 3543cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen return; 3553cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen 3567bcfaf2f431c09c51fe776fc06638b25d3b421c5Johannes Berg debugfs_remove(sdata->debugfs.default_mgmt_key); 3577bcfaf2f431c09c51fe776fc06638b25d3b421c5Johannes Berg sdata->debugfs.default_mgmt_key = NULL; 3583cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen} 3593cfcf6ac6d69dc290e96416731eea5c88ac7d426Jouni Malinen 360e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Bencvoid ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, 361e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc struct sta_info *sta) 362e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc{ 363e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc debugfs_remove(key->debugfs.stalink); 364e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc key->debugfs.stalink = NULL; 365e9f207f0ff90bf60b825800d7450e6f2ff2eab88Jiri Benc} 366