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