/* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * * File: wpactl.c * * Purpose: handle wpa supplicant ioctl input/out functions * * Author: Lyndon Chen * * Date: July 28, 2006 * * Functions: * * Revision History: * */ #include "wpactl.h" #include "key.h" #include "mac.h" #include "device.h" #include "wmgr.h" #include "iocmd.h" #include "iowpa.h" #include "control.h" #include "rndis.h" #include "rf.h" static int msglevel = MSG_LEVEL_INFO; /* * Description: * Set WPA algorithm & keys * * Parameters: * In: * pDevice - * param - * Out: * * Return Value: * */ int wpa_set_keys(struct vnt_private *pDevice, void *ctx) { struct viawget_wpa_param *param = ctx; struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; u32 dwKeyIndex = 0; u8 abyKey[MAX_KEY_LEN]; u8 abySeq[MAX_KEY_LEN]; u64 KeyRSC; u8 byKeyDecMode = KEY_CTL_WEP; int ret = 0; int uu; int ii; if (param->u.wpa_key.alg_name > WPA_ALG_CCMP) return -EINVAL; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "param->u.wpa_key.alg_name = %d \n", param->u.wpa_key.alg_name); if (param->u.wpa_key.alg_name == WPA_ALG_NONE) { pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; pDevice->bEncryptionEnable = false; pDevice->byKeyIndex = 0; pDevice->bTransmitKey = false; for (uu=0; uuu.wpa_key.key && param->u.wpa_key.key_len > sizeof(abyKey)) return -EINVAL; memcpy(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len); dwKeyIndex = (u32)(param->u.wpa_key.key_index); if (param->u.wpa_key.alg_name == WPA_ALG_WEP) { if (dwKeyIndex > 3) { return -EINVAL; } else { if (param->u.wpa_key.set_tx) { pDevice->byKeyIndex = (u8)dwKeyIndex; pDevice->bTransmitKey = true; dwKeyIndex |= (1 << 31); } KeybSetDefaultKey( pDevice, &(pDevice->sKey), dwKeyIndex & ~(BIT30 | USE_KEYRSC), param->u.wpa_key.key_len, NULL, abyKey, KEY_CTL_WEP ); } pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; pDevice->bEncryptionEnable = true; return ret; } if (param->u.wpa_key.seq && param->u.wpa_key.seq_len > sizeof(abySeq)) return -EINVAL; memcpy(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len); if (param->u.wpa_key.seq_len > 0) { for (ii = 0 ; ii < param->u.wpa_key.seq_len ; ii++) { if (ii < 4) KeyRSC |= (abySeq[ii] << (ii * 8)); else KeyRSC |= (abySeq[ii] << ((ii-4) * 8)); } dwKeyIndex |= 1 << 29; } if (param->u.wpa_key.key_index >= MAX_GROUP_KEY) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return dwKeyIndex > 3\n"); return -EINVAL; } if (param->u.wpa_key.alg_name == WPA_ALG_TKIP) { pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; } if (param->u.wpa_key.alg_name == WPA_ALG_CCMP) { pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; } if (param->u.wpa_key.set_tx) dwKeyIndex |= (1 << 31); if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) byKeyDecMode = KEY_CTL_CCMP; else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) byKeyDecMode = KEY_CTL_TKIP; else byKeyDecMode = KEY_CTL_WEP; // Fix HCT test that set 256 bits KEY and Ndis802_11Encryption3Enabled if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) { if (param->u.wpa_key.key_len == MAX_KEY_LEN) byKeyDecMode = KEY_CTL_TKIP; else if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN) byKeyDecMode = KEY_CTL_WEP; else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN) byKeyDecMode = KEY_CTL_WEP; } else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) { if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN) byKeyDecMode = KEY_CTL_WEP; else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN) byKeyDecMode = KEY_CTL_WEP; } // Check TKIP key length if ((byKeyDecMode == KEY_CTL_TKIP) && (param->u.wpa_key.key_len != MAX_KEY_LEN)) { // TKIP Key must be 256 bits DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return - TKIP Key must be 256 bits!\n"); return -EINVAL; } // Check AES key length if ((byKeyDecMode == KEY_CTL_CCMP) && (param->u.wpa_key.key_len != AES_KEY_LEN)) { // AES Key must be 128 bits DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return - AES Key must be 128 bits\n"); return -EINVAL; } if (is_broadcast_ether_addr(¶m->addr[0]) || (param->addr == NULL)) { /* if broadcast, set the key as every key entry's group key */ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Groupe Key Assign.\n"); if ((KeybSetAllGroupKey(pDevice, &(pDevice->sKey), dwKeyIndex, param->u.wpa_key.key_len, &KeyRSC, (u8 *)abyKey, byKeyDecMode ) == true) && (KeybSetDefaultKey(pDevice, &(pDevice->sKey), dwKeyIndex, param->u.wpa_key.key_len, &KeyRSC, (u8 *)abyKey, byKeyDecMode ) == true) ) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GROUP Key Assign.\n"); } else { return -EINVAL; } } else { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Assign.\n"); // BSSID not 0xffffffffffff // Pairwise Key can't be WEP if (byKeyDecMode == KEY_CTL_WEP) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key can't be WEP\n"); return -EINVAL; } dwKeyIndex |= (1 << 30); // set pairwise key if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) { //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - WMAC_CONFIG_IBSS_STA\n")); return -EINVAL; } if (KeybSetKey(pDevice, &(pDevice->sKey), ¶m->addr[0], dwKeyIndex, param->u.wpa_key.key_len, &KeyRSC, (u8 *)abyKey, byKeyDecMode ) == true) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n"); } else { // Key Table Full if (!compare_ether_addr(¶m->addr[0], pDevice->abyBSSID)) { //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -Key Table Full.2\n")); return -EINVAL; } else { // Save Key and configure just before associate/reassociate to BSSID // we do not implement now return -EINVAL; } } } // BSSID not 0xffffffffffff if ((ret == 0) && ((param->u.wpa_key.set_tx) != 0)) { pDevice->byKeyIndex = (u8)param->u.wpa_key.key_index; pDevice->bTransmitKey = true; } pDevice->bEncryptionEnable = true; return ret; }