linux/drivers/staging/vt6655/key.c
<<
>>
Prefs
   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