linux/drivers/staging/vt6656/wpactl.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: wpactl.c
  21 *
  22 * Purpose: handle wpa supplicant ioctl input/out functions
  23 *
  24 * Author: Lyndon Chen
  25 *
  26 * Date: July 28, 2006
  27 *
  28 * Functions:
  29 *
  30 * Revision History:
  31 *
  32 */
  33
  34#include "wpactl.h"
  35#include "key.h"
  36#include "mac.h"
  37#include "device.h"
  38#include "wmgr.h"
  39#include "iocmd.h"
  40#include "iowpa.h"
  41#include "control.h"
  42#include "rndis.h"
  43#include "rf.h"
  44
  45static int msglevel = MSG_LEVEL_INFO;
  46
  47/*
  48 * Description:
  49 *      Set WPA algorithm & keys
  50 *
  51 * Parameters:
  52 *  In:
  53 *      pDevice -
  54 *      param -
  55 *  Out:
  56 *
  57 * Return Value:
  58 *
  59 */
  60int wpa_set_keys(struct vnt_private *pDevice, void *ctx)
  61{
  62        struct viawget_wpa_param *param = ctx;
  63        struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
  64        u32 dwKeyIndex = 0;
  65        u8 abyKey[MAX_KEY_LEN];
  66        u8 abySeq[MAX_KEY_LEN];
  67        u64 KeyRSC;
  68        u8 byKeyDecMode = KEY_CTL_WEP;
  69        int ret = 0;
  70        int uu;
  71        int ii;
  72
  73        if (param->u.wpa_key.alg_name > WPA_ALG_CCMP)
  74                return -EINVAL;
  75
  76        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "param->u.wpa_key.alg_name = %d \n",
  77                param->u.wpa_key.alg_name);
  78        if (param->u.wpa_key.alg_name == WPA_ALG_NONE) {
  79                pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
  80                pDevice->bEncryptionEnable = false;
  81                pDevice->byKeyIndex = 0;
  82                pDevice->bTransmitKey = false;
  83                for (uu=0; uu<MAX_KEY_TABLE; uu++) {
  84                        MACvDisableKeyEntry(pDevice, uu);
  85                }
  86                return ret;
  87        }
  88
  89        if (param->u.wpa_key.key && param->u.wpa_key.key_len > sizeof(abyKey))
  90                return -EINVAL;
  91
  92        memcpy(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len);
  93
  94        dwKeyIndex = (u32)(param->u.wpa_key.key_index);
  95
  96        if (param->u.wpa_key.alg_name == WPA_ALG_WEP) {
  97                if (dwKeyIndex > 3) {
  98                        return -EINVAL;
  99                } else {
 100                        if (param->u.wpa_key.set_tx) {
 101                                pDevice->byKeyIndex = (u8)dwKeyIndex;
 102                                pDevice->bTransmitKey = true;
 103                                dwKeyIndex |= (1 << 31);
 104                        }
 105                        KeybSetDefaultKey(  pDevice,
 106                                        &(pDevice->sKey),
 107                                        dwKeyIndex & ~(BIT30 | USE_KEYRSC),
 108                                        param->u.wpa_key.key_len,
 109                                        NULL,
 110                                        abyKey,
 111                                        KEY_CTL_WEP
 112                                );
 113
 114                }
 115                pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
 116                pDevice->bEncryptionEnable = true;
 117                return ret;
 118        }
 119
 120        if (param->u.wpa_key.seq && param->u.wpa_key.seq_len > sizeof(abySeq))
 121                return -EINVAL;
 122
 123        memcpy(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len);
 124
 125        if (param->u.wpa_key.seq_len > 0) {
 126                for (ii = 0 ; ii < param->u.wpa_key.seq_len ; ii++) {
 127                        if (ii < 4)
 128                                KeyRSC |= (abySeq[ii] << (ii * 8));
 129                        else
 130                                KeyRSC |= (abySeq[ii] << ((ii-4) * 8));
 131                }
 132                dwKeyIndex |= 1 << 29;
 133        }
 134
 135        if (param->u.wpa_key.key_index >= MAX_GROUP_KEY) {
 136                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return  dwKeyIndex > 3\n");
 137                return -EINVAL;
 138        }
 139
 140        if (param->u.wpa_key.alg_name == WPA_ALG_TKIP) {
 141                pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
 142        }
 143
 144        if (param->u.wpa_key.alg_name == WPA_ALG_CCMP) {
 145                pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
 146        }
 147
 148        if (param->u.wpa_key.set_tx)
 149                dwKeyIndex |= (1 << 31);
 150
 151        if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled)
 152                byKeyDecMode = KEY_CTL_CCMP;
 153        else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled)
 154                byKeyDecMode = KEY_CTL_TKIP;
 155        else
 156                byKeyDecMode = KEY_CTL_WEP;
 157
 158        // Fix HCT test that set 256 bits KEY and Ndis802_11Encryption3Enabled
 159        if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
 160                if (param->u.wpa_key.key_len == MAX_KEY_LEN)
 161                        byKeyDecMode = KEY_CTL_TKIP;
 162                else if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN)
 163                        byKeyDecMode = KEY_CTL_WEP;
 164                else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN)
 165                        byKeyDecMode = KEY_CTL_WEP;
 166        } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
 167                if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN)
 168                        byKeyDecMode = KEY_CTL_WEP;
 169                else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN)
 170                        byKeyDecMode = KEY_CTL_WEP;
 171        }
 172
 173        // Check TKIP key length
 174        if ((byKeyDecMode == KEY_CTL_TKIP) &&
 175                (param->u.wpa_key.key_len != MAX_KEY_LEN)) {
 176                // TKIP Key must be 256 bits
 177                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return - TKIP Key must be 256 bits!\n");
 178                return -EINVAL;
 179    }
 180        // Check AES key length
 181        if ((byKeyDecMode == KEY_CTL_CCMP) &&
 182                (param->u.wpa_key.key_len != AES_KEY_LEN)) {
 183                // AES Key must be 128 bits
 184                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return - AES Key must be 128 bits\n");
 185                return -EINVAL;
 186        }
 187
 188        if (is_broadcast_ether_addr(&param->addr[0]) || (param->addr == NULL)) {
 189                /* if broadcast, set the key as every key entry's group key */
 190                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Groupe Key Assign.\n");
 191
 192                if ((KeybSetAllGroupKey(pDevice, &(pDevice->sKey), dwKeyIndex,
 193                                                        param->u.wpa_key.key_len,
 194                                                        &KeyRSC,
 195                                                        (u8 *)abyKey,
 196                                                        byKeyDecMode
 197                                        ) == true) &&
 198                        (KeybSetDefaultKey(pDevice,
 199                                        &(pDevice->sKey),
 200                                        dwKeyIndex,
 201                                        param->u.wpa_key.key_len,
 202                                        &KeyRSC,
 203                                        (u8 *)abyKey,
 204                                        byKeyDecMode
 205                                ) == true) ) {
 206                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GROUP Key Assign.\n");
 207                } else {
 208                        return -EINVAL;
 209                }
 210        } else {
 211                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Assign.\n");
 212                // BSSID not 0xffffffffffff
 213                // Pairwise Key can't be WEP
 214                if (byKeyDecMode == KEY_CTL_WEP) {
 215                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key can't be WEP\n");
 216                        return -EINVAL;
 217                }
 218                dwKeyIndex |= (1 << 30); // set pairwise key
 219                if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) {
 220                        //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - WMAC_CONFIG_IBSS_STA\n"));
 221                        return -EINVAL;
 222                }
 223                if (KeybSetKey(pDevice, &(pDevice->sKey), &param->addr[0],
 224                                dwKeyIndex, param->u.wpa_key.key_len,
 225                                &KeyRSC, (u8 *)abyKey, byKeyDecMode
 226                                ) == true) {
 227                        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n");
 228                } else {
 229                        // Key Table Full
 230                        if (!compare_ether_addr(&param->addr[0], pDevice->abyBSSID)) {
 231                                //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -Key Table Full.2\n"));
 232                                return -EINVAL;
 233                        } else {
 234                                // Save Key and configure just before associate/reassociate to BSSID
 235                                // we do not implement now
 236                                return -EINVAL;
 237                        }
 238                }
 239        } // BSSID not 0xffffffffffff
 240        if ((ret == 0) && ((param->u.wpa_key.set_tx) != 0)) {
 241                pDevice->byKeyIndex = (u8)param->u.wpa_key.key_index;
 242                pDevice->bTransmitKey = true;
 243        }
 244        pDevice->bEncryptionEnable = true;
 245
 246        return ret;
 247}
 248
 249