linux/drivers/staging/vt6656/wpa2.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: wpa2.c
  21 *
  22 * Purpose: Handles the Basic Service Set & Node Database functions
  23 *
  24 * Functions:
  25 *
  26 * Revision History:
  27 *
  28 * Author: Yiching Chen
  29 *
  30 * Date: Oct. 4, 2004
  31 *
  32 */
  33
  34#include "device.h"
  35#include "wpa2.h"
  36
  37static int          msglevel                =MSG_LEVEL_INFO;
  38//static int          msglevel                =MSG_LEVEL_DEBUG;
  39
  40static const u8 abyOUIGK[4]      = { 0x00, 0x0F, 0xAC, 0x00 };
  41static const u8 abyOUIWEP40[4]   = { 0x00, 0x0F, 0xAC, 0x01 };
  42static const u8 abyOUIWEP104[4]  = { 0x00, 0x0F, 0xAC, 0x05 };
  43static const u8 abyOUITKIP[4]    = { 0x00, 0x0F, 0xAC, 0x02 };
  44static const u8 abyOUICCMP[4]    = { 0x00, 0x0F, 0xAC, 0x04 };
  45
  46static const u8 abyOUI8021X[4]   = { 0x00, 0x0F, 0xAC, 0x01 };
  47static const u8 abyOUIPSK[4]     = { 0x00, 0x0F, 0xAC, 0x02 };
  48
  49/*+
  50 *
  51 * Description:
  52 *    Clear RSN information in BSSList.
  53 *
  54 * Parameters:
  55 *  In:
  56 *      pBSSNode - BSS list.
  57 *  Out:
  58 *      none
  59 *
  60 * Return Value: none.
  61 *
  62-*/
  63void
  64WPA2_ClearRSN (
  65     PKnownBSS        pBSSNode
  66    )
  67{
  68    int ii;
  69
  70    pBSSNode->bWPA2Valid = false;
  71
  72    pBSSNode->byCSSGK = WLAN_11i_CSS_CCMP;
  73    for (ii=0; ii < 4; ii ++)
  74        pBSSNode->abyCSSPK[ii] = WLAN_11i_CSS_CCMP;
  75    pBSSNode->wCSSPKCount = 1;
  76    for (ii=0; ii < 4; ii ++)
  77        pBSSNode->abyAKMSSAuthType[ii] = WLAN_11i_AKMSS_802_1X;
  78    pBSSNode->wAKMSSAuthCount = 1;
  79    pBSSNode->sRSNCapObj.bRSNCapExist = false;
  80    pBSSNode->sRSNCapObj.wRSNCap = 0;
  81}
  82
  83/*+
  84 *
  85 * Description:
  86 *    Parse RSN IE.
  87 *
  88 * Parameters:
  89 *  In:
  90 *      pBSSNode - BSS list.
  91 *      pRSN - Pointer to the RSN IE.
  92 *  Out:
  93 *      none
  94 *
  95 * Return Value: none.
  96 *
  97-*/
  98void
  99WPA2vParseRSN (
 100     PKnownBSS        pBSSNode,
 101     PWLAN_IE_RSN     pRSN
 102    )
 103{
 104    int                 i, j;
 105    u16                m = 0, n = 0;
 106    u8 *               pbyOUI;
 107    bool                bUseGK = false;
 108
 109    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"WPA2_ParseRSN: [%d]\n", pRSN->len);
 110
 111    WPA2_ClearRSN(pBSSNode);
 112
 113    if (pRSN->len == 2) { // ver(2)
 114        if ((pRSN->byElementID == WLAN_EID_RSN) && (pRSN->wVersion == 1)) {
 115            pBSSNode->bWPA2Valid = true;
 116        }
 117        return;
 118    }
 119
 120    if (pRSN->len < 6) { // ver(2) + GK(4)
 121        // invalid CSS, P802.11i/D10.0, p31
 122        return;
 123    }
 124
 125    // information element header makes sense
 126    if ((pRSN->byElementID == WLAN_EID_RSN) &&
 127        (pRSN->wVersion == 1)) {
 128
 129        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Legal 802.11i RSN\n");
 130
 131        pbyOUI = &(pRSN->abyRSN[0]);
 132        if ( !memcmp(pbyOUI, abyOUIWEP40, 4))
 133            pBSSNode->byCSSGK = WLAN_11i_CSS_WEP40;
 134        else if ( !memcmp(pbyOUI, abyOUITKIP, 4))
 135            pBSSNode->byCSSGK = WLAN_11i_CSS_TKIP;
 136        else if ( !memcmp(pbyOUI, abyOUICCMP, 4))
 137            pBSSNode->byCSSGK = WLAN_11i_CSS_CCMP;
 138        else if ( !memcmp(pbyOUI, abyOUIWEP104, 4))
 139            pBSSNode->byCSSGK = WLAN_11i_CSS_WEP104;
 140        else if ( !memcmp(pbyOUI, abyOUIGK, 4)) {
 141            // invalid CSS, P802.11i/D10.0, p32
 142            return;
 143        } else
 144            // any vendor checks here
 145            pBSSNode->byCSSGK = WLAN_11i_CSS_UNKNOWN;
 146
 147        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"802.11i CSS: %X\n", pBSSNode->byCSSGK);
 148
 149        if (pRSN->len == 6) {
 150            pBSSNode->bWPA2Valid = true;
 151            return;
 152        }
 153
 154        if (pRSN->len >= 8) { // ver(2) + GK(4) + PK count(2)
 155            pBSSNode->wCSSPKCount = *((u16 *) &(pRSN->abyRSN[4]));
 156            j = 0;
 157            pbyOUI = &(pRSN->abyRSN[6]);
 158
 159            for (i = 0; (i < pBSSNode->wCSSPKCount) && (j < sizeof(pBSSNode->abyCSSPK)/sizeof(u8)); i++) {
 160
 161                if (pRSN->len >= 8+i*4+4) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*i)
 162                    if ( !memcmp(pbyOUI, abyOUIGK, 4)) {
 163                        pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_USE_GROUP;
 164                        bUseGK = true;
 165                    } else if ( !memcmp(pbyOUI, abyOUIWEP40, 4)) {
 166                        // Invalid CSS, continue parsing
 167                    } else if ( !memcmp(pbyOUI, abyOUITKIP, 4)) {
 168                        if (pBSSNode->byCSSGK != WLAN_11i_CSS_CCMP)
 169                            pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_TKIP;
 170                        else
 171                            ; // Invalid CSS, continue parsing
 172                    } else if ( !memcmp(pbyOUI, abyOUICCMP, 4)) {
 173                        pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_CCMP;
 174                    } else if ( !memcmp(pbyOUI, abyOUIWEP104, 4)) {
 175                        // Invalid CSS, continue parsing
 176                    } else {
 177                        // any vendor checks here
 178                        pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_UNKNOWN;
 179                    }
 180                    pbyOUI += 4;
 181                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"abyCSSPK[%d]: %X\n", j-1, pBSSNode->abyCSSPK[j-1]);
 182                } else
 183                    break;
 184            } //for
 185
 186            if (bUseGK == true) {
 187                if (j != 1) {
 188                    // invalid CSS, This should be only PK CSS.
 189                    return;
 190                }
 191                if (pBSSNode->byCSSGK == WLAN_11i_CSS_CCMP) {
 192                    // invalid CSS, If CCMP is enable , PK can't be CSSGK.
 193                    return;
 194                }
 195            }
 196            if ((pBSSNode->wCSSPKCount != 0) && (j == 0)) {
 197                // invalid CSS, No valid PK.
 198                return;
 199            }
 200            pBSSNode->wCSSPKCount = (u16)j;
 201            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wCSSPKCount: %d\n", pBSSNode->wCSSPKCount);
 202        }
 203
 204        m = *((u16 *) &(pRSN->abyRSN[4]));
 205
 206        if (pRSN->len >= 10+m*4) { // ver(2) + GK(4) + PK count(2) + PKS(4*m) + AKMSS count(2)
 207            pBSSNode->wAKMSSAuthCount = *((u16 *) &(pRSN->abyRSN[6+4*m]));
 208            j = 0;
 209            pbyOUI = &(pRSN->abyRSN[8+4*m]);
 210            for (i = 0; (i < pBSSNode->wAKMSSAuthCount) && (j < sizeof(pBSSNode->abyAKMSSAuthType)/sizeof(u8)); i++) {
 211                if (pRSN->len >= 10+(m+i)*4+4) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*m)+AKMSS(2)+AKS(4*i)
 212                    if ( !memcmp(pbyOUI, abyOUI8021X, 4))
 213                        pBSSNode->abyAKMSSAuthType[j++] = WLAN_11i_AKMSS_802_1X;
 214                    else if ( !memcmp(pbyOUI, abyOUIPSK, 4))
 215                        pBSSNode->abyAKMSSAuthType[j++] = WLAN_11i_AKMSS_PSK;
 216                    else
 217                        // any vendor checks here
 218                        pBSSNode->abyAKMSSAuthType[j++] = WLAN_11i_AKMSS_UNKNOWN;
 219                    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"abyAKMSSAuthType[%d]: %X\n", j-1, pBSSNode->abyAKMSSAuthType[j-1]);
 220                } else
 221                    break;
 222            }
 223            pBSSNode->wAKMSSAuthCount = (u16)j;
 224            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wAKMSSAuthCount: %d\n", pBSSNode->wAKMSSAuthCount);
 225
 226            n = *((u16 *) &(pRSN->abyRSN[6+4*m]));
 227            if (pRSN->len >= 12+4*m+4*n) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*m)+AKMSSCnt(2)+AKMSS(4*n)+Cap(2)
 228                pBSSNode->sRSNCapObj.bRSNCapExist = true;
 229                pBSSNode->sRSNCapObj.wRSNCap = *((u16 *) &(pRSN->abyRSN[8+4*m+4*n]));
 230            }
 231        }
 232        //ignore PMKID lists bcs only (Re)Assocrequest has this field
 233        pBSSNode->bWPA2Valid = true;
 234    }
 235}
 236