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