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 * 16 * File: key.c 17 * 18 * Purpose: Implement functions for 802.11i Key management 19 * 20 * Author: Jerry Chen 21 * 22 * Date: May 29, 2003 23 * 24 * Functions: 25 * 26 * Revision History: 27 * 28 */ 29 30 #include "mac.h" 31 #include "key.h" 32 #include "usbpipe.h" 33 34 int vnt_key_init_table(struct vnt_private *priv) 35 { 36 u8 i; 37 u8 data[MAX_KEY_TABLE]; 38 39 for (i = 0; i < MAX_KEY_TABLE; i++) 40 data[i] = i; 41 42 return vnt_control_out(priv, MESSAGE_TYPE_CLRKEYENTRY, 43 0, 0, ARRAY_SIZE(data), data); 44 } 45 46 static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr, 47 struct ieee80211_key_conf *key, u32 key_type, u32 mode, 48 bool onfly_latch) 49 { 50 struct vnt_private *priv = hw->priv; 51 u8 broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 52 u16 key_mode = 0; 53 u32 entry = 0; 54 u8 *bssid; 55 u8 key_inx = key->keyidx; 56 u8 i; 57 58 if (mac_addr) 59 bssid = mac_addr; 60 else 61 bssid = &broadcast[0]; 62 63 if (key_type != VNT_KEY_DEFAULTKEY) { 64 for (i = 0; i < (MAX_KEY_TABLE - 1); i++) { 65 if (!test_bit(i, &priv->key_entry_inuse)) { 66 set_bit(i, &priv->key_entry_inuse); 67 68 key->hw_key_idx = i; 69 entry = key->hw_key_idx; 70 break; 71 } 72 } 73 } 74 75 switch (key_type) { 76 /* fallthrough */ 77 case VNT_KEY_DEFAULTKEY: 78 /* default key last entry */ 79 entry = MAX_KEY_TABLE - 1; 80 key->hw_key_idx = entry; 81 case VNT_KEY_ALLGROUP: 82 key_mode |= VNT_KEY_ALLGROUP; 83 if (onfly_latch) 84 key_mode |= VNT_KEY_ONFLY_ALL; 85 case VNT_KEY_GROUP_ADDRESS: 86 key_mode |= mode; 87 case VNT_KEY_GROUP: 88 key_mode |= (mode << 4); 89 key_mode |= VNT_KEY_GROUP; 90 break; 91 case VNT_KEY_PAIRWISE: 92 key_mode |= mode; 93 key_inx = 4; 94 /* Don't save entry for pairwise key for station mode */ 95 if (priv->op_mode == NL80211_IFTYPE_STATION) 96 clear_bit(entry, &priv->key_entry_inuse); 97 break; 98 default: 99 return -EINVAL; 100 } 101 102 if (onfly_latch) 103 key_mode |= VNT_KEY_ONFLY; 104 105 if (mode == KEY_CTL_WEP) { 106 if (key->keylen == WLAN_KEY_LEN_WEP40) 107 key->key[15] &= 0x7f; 108 if (key->keylen == WLAN_KEY_LEN_WEP104) 109 key->key[15] |= 0x80; 110 } 111 112 vnt_mac_set_keyentry(priv, key_mode, entry, key_inx, bssid, key->key); 113 114 return 0; 115 } 116 117 int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta, 118 struct ieee80211_vif *vif, struct ieee80211_key_conf *key) 119 { 120 struct ieee80211_bss_conf *conf = &vif->bss_conf; 121 struct vnt_private *priv = hw->priv; 122 u8 *mac_addr = NULL; 123 u8 key_dec_mode = 0; 124 int ret = 0, u; 125 126 if (sta) 127 mac_addr = &sta->addr[0]; 128 129 switch (key->cipher) { 130 case 0: 131 for (u = 0 ; u < MAX_KEY_TABLE; u++) 132 vnt_mac_disable_keyentry(priv, u); 133 return ret; 134 135 case WLAN_CIPHER_SUITE_WEP40: 136 case WLAN_CIPHER_SUITE_WEP104: 137 for (u = 0; u < MAX_KEY_TABLE; u++) 138 vnt_mac_disable_keyentry(priv, u); 139 140 vnt_set_keymode(hw, mac_addr, key, VNT_KEY_DEFAULTKEY, 141 KEY_CTL_WEP, true); 142 143 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; 144 145 return ret; 146 case WLAN_CIPHER_SUITE_TKIP: 147 key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; 148 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; 149 150 key_dec_mode = KEY_CTL_TKIP; 151 152 break; 153 case WLAN_CIPHER_SUITE_CCMP: 154 if (priv->local_id <= MAC_REVISION_A1) 155 return -EINVAL; 156 157 key_dec_mode = KEY_CTL_CCMP; 158 159 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; 160 } 161 162 if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { 163 vnt_set_keymode(hw, mac_addr, key, VNT_KEY_PAIRWISE, 164 key_dec_mode, true); 165 } else { 166 vnt_set_keymode(hw, mac_addr, key, VNT_KEY_DEFAULTKEY, 167 key_dec_mode, true); 168 169 vnt_set_keymode(hw, (u8 *)conf->bssid, key, 170 VNT_KEY_GROUP_ADDRESS, key_dec_mode, true); 171 } 172 173 return 0; 174 } 175