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 */ 29 30 #include "tmacro.h" 31 #include "key.h" 32 #include "mac.h" 33 34 static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr, 35 struct ieee80211_key_conf *key, u32 key_type, u32 mode, 36 bool onfly_latch) 37 { 38 struct vnt_private *priv = hw->priv; 39 u8 broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 40 u16 key_mode = 0; 41 u32 entry = 0; 42 u8 *bssid; 43 u8 key_inx = key->keyidx; 44 u8 i; 45 46 if (mac_addr) 47 bssid = mac_addr; 48 else 49 bssid = &broadcast[0]; 50 51 if (key_type != VNT_KEY_DEFAULTKEY) { 52 for (i = 0; i < (MAX_KEY_TABLE - 1); i++) { 53 if (!test_bit(i, &priv->key_entry_inuse)) { 54 set_bit(i, &priv->key_entry_inuse); 55 56 key->hw_key_idx = i; 57 entry = key->hw_key_idx; 58 break; 59 } 60 } 61 } 62 63 switch (key_type) { 64 /* fallthrough */ 65 case VNT_KEY_DEFAULTKEY: 66 /* default key last entry */ 67 entry = MAX_KEY_TABLE - 1; 68 key->hw_key_idx = entry; 69 case VNT_KEY_ALLGROUP: 70 key_mode |= VNT_KEY_ALLGROUP; 71 if (onfly_latch) 72 key_mode |= VNT_KEY_ONFLY_ALL; 73 case VNT_KEY_GROUP_ADDRESS: 74 key_mode |= mode; 75 case VNT_KEY_GROUP: 76 key_mode |= (mode << 4); 77 key_mode |= VNT_KEY_GROUP; 78 break; 79 case VNT_KEY_PAIRWISE: 80 key_mode |= mode; 81 key_inx = 4; 82 break; 83 default: 84 return -EINVAL; 85 } 86 87 if (onfly_latch) 88 key_mode |= VNT_KEY_ONFLY; 89 90 if (mode == KEY_CTL_WEP) { 91 if (key->keylen == WLAN_KEY_LEN_WEP40) 92 key->key[15] &= 0x7f; 93 if (key->keylen == WLAN_KEY_LEN_WEP104) 94 key->key[15] |= 0x80; 95 } 96 97 MACvSetKeyEntry(priv, key_mode, entry, key_inx, 98 bssid, (u32 *)key->key, priv->byLocalID); 99 100 return 0; 101 } 102 103 int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta, 104 struct ieee80211_vif *vif, struct ieee80211_key_conf *key) 105 { 106 struct ieee80211_bss_conf *conf = &vif->bss_conf; 107 struct vnt_private *priv = hw->priv; 108 u8 *mac_addr = NULL; 109 u8 key_dec_mode = 0; 110 int ret = 0; 111 u32 u; 112 113 if (sta) 114 mac_addr = &sta->addr[0]; 115 116 switch (key->cipher) { 117 case 0: 118 for (u = 0 ; u < MAX_KEY_TABLE; u++) 119 MACvDisableKeyEntry(priv, u); 120 return ret; 121 122 case WLAN_CIPHER_SUITE_WEP40: 123 case WLAN_CIPHER_SUITE_WEP104: 124 for (u = 0; u < MAX_KEY_TABLE; u++) 125 MACvDisableKeyEntry(priv, u); 126 127 vnt_set_keymode(hw, mac_addr, 128 key, VNT_KEY_DEFAULTKEY, KEY_CTL_WEP, true); 129 130 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; 131 132 return ret; 133 case WLAN_CIPHER_SUITE_TKIP: 134 key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; 135 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; 136 137 key_dec_mode = KEY_CTL_TKIP; 138 139 break; 140 case WLAN_CIPHER_SUITE_CCMP: 141 key_dec_mode = KEY_CTL_CCMP; 142 143 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; 144 } 145 146 if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { 147 vnt_set_keymode(hw, mac_addr, 148 key, VNT_KEY_PAIRWISE, key_dec_mode, true); 149 } else { 150 vnt_set_keymode(hw, mac_addr, 151 key, VNT_KEY_DEFAULTKEY, key_dec_mode, true); 152 153 vnt_set_keymode(hw, (u8 *)conf->bssid, 154 key, VNT_KEY_GROUP_ADDRESS, key_dec_mode, true); 155 } 156 157 return 0; 158 } 159