1 /* 2 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. 3 * All rights reserved. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * 20 * File: key.c 21 * 22 * Purpose: Implement functions for 802.11i Key management 23 * 24 * Author: Jerry Chen 25 * 26 * Date: May 29, 2003 27 * 28 * Functions: 29 * 30 * Revision History: 31 * 32 */ 33 34 #include "mac.h" 35 #include "key.h" 36 #include "usbpipe.h" 37 38 int vnt_key_init_table(struct vnt_private *priv) 39 { 40 u8 i; 41 u8 data[MAX_KEY_TABLE]; 42 43 for (i = 0; i < MAX_KEY_TABLE; i++) 44 data[i] = i; 45 46 return vnt_control_out(priv, MESSAGE_TYPE_CLRKEYENTRY, 47 0, 0, ARRAY_SIZE(data), data); 48 } 49 50 static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr, 51 struct ieee80211_key_conf *key, u32 key_type, u32 mode, 52 bool onfly_latch) 53 { 54 struct vnt_private *priv = hw->priv; 55 u8 broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 56 u16 key_mode = 0; 57 u32 entry = 0; 58 u8 *bssid; 59 u8 key_inx = key->keyidx; 60 u8 i; 61 62 if (mac_addr) 63 bssid = mac_addr; 64 else 65 bssid = &broadcast[0]; 66 67 if (key_type != VNT_KEY_DEFAULTKEY) { 68 for (i = 0; i < (MAX_KEY_TABLE - 1); i++) { 69 if (!test_bit(i, &priv->key_entry_inuse)) { 70 set_bit(i, &priv->key_entry_inuse); 71 72 key->hw_key_idx = i; 73 entry = key->hw_key_idx; 74 break; 75 } 76 } 77 } 78 79 switch (key_type) { 80 /* fallthrough */ 81 case VNT_KEY_DEFAULTKEY: 82 /* default key last entry */ 83 entry = MAX_KEY_TABLE - 1; 84 key->hw_key_idx = entry; 85 case VNT_KEY_ALLGROUP: 86 key_mode |= VNT_KEY_ALLGROUP; 87 if (onfly_latch) 88 key_mode |= VNT_KEY_ONFLY_ALL; 89 case VNT_KEY_GROUP_ADDRESS: 90 key_mode |= mode; 91 case VNT_KEY_GROUP: 92 key_mode |= (mode << 4); 93 key_mode |= VNT_KEY_GROUP; 94 break; 95 case VNT_KEY_PAIRWISE: 96 key_mode |= mode; 97 key_inx = 4; 98 /* Don't save entry for pairwise key for station mode */ 99 if (priv->op_mode == NL80211_IFTYPE_STATION) 100 clear_bit(entry, &priv->key_entry_inuse); 101 break; 102 default: 103 return -EINVAL; 104 } 105 106 if (onfly_latch) 107 key_mode |= VNT_KEY_ONFLY; 108 109 if (mode == KEY_CTL_WEP) { 110 if (key->keylen == WLAN_KEY_LEN_WEP40) 111 key->key[15] &= 0x7f; 112 if (key->keylen == WLAN_KEY_LEN_WEP104) 113 key->key[15] |= 0x80; 114 } 115 116 vnt_mac_set_keyentry(priv, key_mode, entry, key_inx, bssid, key->key); 117 118 return 0; 119 } 120 121 int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta, 122 struct ieee80211_vif *vif, struct ieee80211_key_conf *key) 123 { 124 struct ieee80211_bss_conf *conf = &vif->bss_conf; 125 struct vnt_private *priv = hw->priv; 126 u8 *mac_addr = NULL; 127 u8 key_dec_mode = 0; 128 int ret = 0, u; 129 130 if (sta) 131 mac_addr = &sta->addr[0]; 132 133 switch (key->cipher) { 134 case 0: 135 for (u = 0 ; u < MAX_KEY_TABLE; u++) 136 vnt_mac_disable_keyentry(priv, u); 137 return ret; 138 139 case WLAN_CIPHER_SUITE_WEP40: 140 case WLAN_CIPHER_SUITE_WEP104: 141 for (u = 0; u < MAX_KEY_TABLE; u++) 142 vnt_mac_disable_keyentry(priv, u); 143 144 vnt_set_keymode(hw, mac_addr, key, VNT_KEY_DEFAULTKEY, 145 KEY_CTL_WEP, true); 146 147 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; 148 149 return ret; 150 case WLAN_CIPHER_SUITE_TKIP: 151 key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; 152 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; 153 154 key_dec_mode = KEY_CTL_TKIP; 155 156 break; 157 case WLAN_CIPHER_SUITE_CCMP: 158 if (priv->local_id <= MAC_REVISION_A1) 159 return -EINVAL; 160 161 key_dec_mode = KEY_CTL_CCMP; 162 163 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; 164 } 165 166 167 if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { 168 vnt_set_keymode(hw, mac_addr, key, VNT_KEY_PAIRWISE, 169 key_dec_mode, true); 170 } else { 171 vnt_set_keymode(hw, mac_addr, key, VNT_KEY_DEFAULTKEY, 172 key_dec_mode, true); 173 174 vnt_set_keymode(hw, (u8 *)conf->bssid, key, 175 VNT_KEY_GROUP_ADDRESS, key_dec_mode, true); 176 } 177 178 return 0; 179 } 180