Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.16 357 lines 11 kB view raw
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 "wpa2.h" 35#include "device.h" 36#include "wmgr.h" 37 38/*--------------------- Static Definitions -------------------------*/ 39static int msglevel = MSG_LEVEL_INFO; 40/*--------------------- Static Classes ----------------------------*/ 41 42/*--------------------- Static Variables --------------------------*/ 43 44static const unsigned char abyOUIGK[4] = { 0x00, 0x0F, 0xAC, 0x00 }; 45static const unsigned char abyOUIWEP40[4] = { 0x00, 0x0F, 0xAC, 0x01 }; 46static const unsigned char abyOUIWEP104[4] = { 0x00, 0x0F, 0xAC, 0x05 }; 47static const unsigned char abyOUITKIP[4] = { 0x00, 0x0F, 0xAC, 0x02 }; 48static const unsigned char abyOUICCMP[4] = { 0x00, 0x0F, 0xAC, 0x04 }; 49 50static const unsigned char abyOUI8021X[4] = { 0x00, 0x0F, 0xAC, 0x01 }; 51static const unsigned char abyOUIPSK[4] = { 0x00, 0x0F, 0xAC, 0x02 }; 52 53/*--------------------- Static Functions --------------------------*/ 54 55/*--------------------- Export Variables --------------------------*/ 56 57/*--------------------- Export Functions --------------------------*/ 58 59/*+ 60 * 61 * Description: 62 * Clear RSN information in BSSList. 63 * 64 * Parameters: 65 * In: 66 * pBSSNode - BSS list. 67 * Out: 68 * none 69 * 70 * Return Value: none. 71 * 72 -*/ 73void 74WPA2_ClearRSN( 75 PKnownBSS pBSSNode 76) 77{ 78 int ii; 79 80 pBSSNode->bWPA2Valid = false; 81 82 pBSSNode->byCSSGK = WLAN_11i_CSS_CCMP; 83 for (ii = 0; ii < 4; ii++) 84 pBSSNode->abyCSSPK[ii] = WLAN_11i_CSS_CCMP; 85 pBSSNode->wCSSPKCount = 1; 86 for (ii = 0; ii < 4; ii++) 87 pBSSNode->abyAKMSSAuthType[ii] = WLAN_11i_AKMSS_802_1X; 88 pBSSNode->wAKMSSAuthCount = 1; 89 pBSSNode->sRSNCapObj.bRSNCapExist = false; 90 pBSSNode->sRSNCapObj.wRSNCap = 0; 91} 92 93/*+ 94 * 95 * Description: 96 * Parse RSN IE. 97 * 98 * Parameters: 99 * In: 100 * pBSSNode - BSS list. 101 * pRSN - Pointer to the RSN IE. 102 * Out: 103 * none 104 * 105 * Return Value: none. 106 * 107 -*/ 108void 109WPA2vParseRSN( 110 PKnownBSS pBSSNode, 111 PWLAN_IE_RSN pRSN 112) 113{ 114 int i, j; 115 unsigned short m = 0, n = 0; 116 unsigned char *pbyOUI; 117 bool bUseGK = false; 118 119 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "WPA2_ParseRSN: [%d]\n", pRSN->len); 120 121 WPA2_ClearRSN(pBSSNode); 122 123 if (pRSN->len == 2) { // ver(2) 124 if ((pRSN->byElementID == WLAN_EID_RSN) && (pRSN->wVersion == 1)) 125 pBSSNode->bWPA2Valid = true; 126 127 return; 128 } 129 130 if (pRSN->len < 6) { // ver(2) + GK(4) 131 // invalid CSS, P802.11i/D10.0, p31 132 return; 133 } 134 135 // information element header makes sense 136 if ((pRSN->byElementID == WLAN_EID_RSN) && 137 (pRSN->wVersion == 1)) { 138 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Legal 802.11i RSN\n"); 139 140 pbyOUI = &(pRSN->abyRSN[0]); 141 if (!memcmp(pbyOUI, abyOUIWEP40, 4)) 142 pBSSNode->byCSSGK = WLAN_11i_CSS_WEP40; 143 else if (!memcmp(pbyOUI, abyOUITKIP, 4)) 144 pBSSNode->byCSSGK = WLAN_11i_CSS_TKIP; 145 else if (!memcmp(pbyOUI, abyOUICCMP, 4)) 146 pBSSNode->byCSSGK = WLAN_11i_CSS_CCMP; 147 else if (!memcmp(pbyOUI, abyOUIWEP104, 4)) 148 pBSSNode->byCSSGK = WLAN_11i_CSS_WEP104; 149 else if (!memcmp(pbyOUI, abyOUIGK, 4)) { 150 // invalid CSS, P802.11i/D10.0, p32 151 return; 152 } else 153 // any vendor checks here 154 pBSSNode->byCSSGK = WLAN_11i_CSS_UNKNOWN; 155 156 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "802.11i CSS: %X\n", pBSSNode->byCSSGK); 157 158 if (pRSN->len == 6) { 159 pBSSNode->bWPA2Valid = true; 160 return; 161 } 162 163 if (pRSN->len >= 8) { // ver(2) + GK(4) + PK count(2) 164 pBSSNode->wCSSPKCount = *((unsigned short *)&(pRSN->abyRSN[4])); 165 j = 0; 166 pbyOUI = &(pRSN->abyRSN[6]); 167 168 for (i = 0; (i < pBSSNode->wCSSPKCount) && (j < sizeof(pBSSNode->abyCSSPK)/sizeof(unsigned char)); i++) { 169 if (pRSN->len >= 8+i*4+4) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*i) 170 if (!memcmp(pbyOUI, abyOUIGK, 4)) { 171 pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_USE_GROUP; 172 bUseGK = true; 173 } else if (!memcmp(pbyOUI, abyOUIWEP40, 4)) { 174 // Invalid CSS, continue to parsing 175 } else if (!memcmp(pbyOUI, abyOUITKIP, 4)) { 176 if (pBSSNode->byCSSGK != WLAN_11i_CSS_CCMP) 177 pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_TKIP; 178 else 179 ; // Invalid CSS, continue to parsing 180 } else if (!memcmp(pbyOUI, abyOUICCMP, 4)) { 181 pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_CCMP; 182 } else if (!memcmp(pbyOUI, abyOUIWEP104, 4)) { 183 // Invalid CSS, continue to parsing 184 } else { 185 // any vendor checks here 186 pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_UNKNOWN; 187 } 188 pbyOUI += 4; 189 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "abyCSSPK[%d]: %X\n", j-1, pBSSNode->abyCSSPK[j-1]); 190 } else 191 break; 192 } //for 193 194 if (bUseGK) { 195 if (j != 1) { 196 // invalid CSS, This should be only PK CSS. 197 return; 198 } 199 if (pBSSNode->byCSSGK == WLAN_11i_CSS_CCMP) { 200 // invalid CSS, If CCMP is enable , PK can't be CSSGK. 201 return; 202 } 203 } 204 if ((pBSSNode->wCSSPKCount != 0) && (j == 0)) { 205 // invalid CSS, No valid PK. 206 return; 207 } 208 pBSSNode->wCSSPKCount = (unsigned short)j; 209 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wCSSPKCount: %d\n", pBSSNode->wCSSPKCount); 210 } 211 212 m = *((unsigned short *)&(pRSN->abyRSN[4])); 213 214 if (pRSN->len >= 10+m*4) { // ver(2) + GK(4) + PK count(2) + PKS(4*m) + AKMSS count(2) 215 pBSSNode->wAKMSSAuthCount = *((unsigned short *)&(pRSN->abyRSN[6+4*m])); 216 j = 0; 217 pbyOUI = &(pRSN->abyRSN[8+4*m]); 218 for (i = 0; (i < pBSSNode->wAKMSSAuthCount) && (j < sizeof(pBSSNode->abyAKMSSAuthType)/sizeof(unsigned char)); i++) { 219 if (pRSN->len >= 10+(m+i)*4+4) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*m)+AKMSS(2)+AKS(4*i) 220 if (!memcmp(pbyOUI, abyOUI8021X, 4)) 221 pBSSNode->abyAKMSSAuthType[j++] = WLAN_11i_AKMSS_802_1X; 222 else if (!memcmp(pbyOUI, abyOUIPSK, 4)) 223 pBSSNode->abyAKMSSAuthType[j++] = WLAN_11i_AKMSS_PSK; 224 else 225 // any vendor checks here 226 pBSSNode->abyAKMSSAuthType[j++] = WLAN_11i_AKMSS_UNKNOWN; 227 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "abyAKMSSAuthType[%d]: %X\n", j-1, pBSSNode->abyAKMSSAuthType[j-1]); 228 } else 229 break; 230 } 231 pBSSNode->wAKMSSAuthCount = (unsigned short)j; 232 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wAKMSSAuthCount: %d\n", pBSSNode->wAKMSSAuthCount); 233 234 n = *((unsigned short *)&(pRSN->abyRSN[6+4*m])); 235 if (pRSN->len >= 12 + 4 * m + 4 * n) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*m)+AKMSSCnt(2)+AKMSS(4*n)+Cap(2) 236 pBSSNode->sRSNCapObj.bRSNCapExist = true; 237 pBSSNode->sRSNCapObj.wRSNCap = *((unsigned short *)&(pRSN->abyRSN[8+4*m+4*n])); 238 } 239 } 240 //ignore PMKID lists bcs only (Re)Assocrequest has this field 241 pBSSNode->bWPA2Valid = true; 242 } 243} 244 245/*+ 246 * 247 * Description: 248 * Set WPA IEs 249 * 250 * Parameters: 251 * In: 252 * pMgmtHandle - Pointer to management object 253 * Out: 254 * pRSNIEs - Pointer to the RSN IE to set. 255 * 256 * Return Value: length of IEs. 257 * 258 -*/ 259unsigned int 260WPA2uSetIEs( 261 void *pMgmtHandle, 262 PWLAN_IE_RSN pRSNIEs 263) 264{ 265 PSMgmtObject pMgmt = (PSMgmtObject) pMgmtHandle; 266 unsigned char *pbyBuffer = NULL; 267 unsigned int ii = 0; 268 unsigned short *pwPMKID = NULL; 269 270 if (pRSNIEs == NULL) 271 return 0; 272 273 if (((pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || 274 (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) && 275 (pMgmt->pCurrBSS != NULL)) { 276 /* WPA2 IE */ 277 pbyBuffer = (unsigned char *)pRSNIEs; 278 pRSNIEs->byElementID = WLAN_EID_RSN; 279 pRSNIEs->len = 6; //Version(2)+GK(4) 280 pRSNIEs->wVersion = 1; 281 //Group Key Cipher Suite 282 pRSNIEs->abyRSN[0] = 0x00; 283 pRSNIEs->abyRSN[1] = 0x0F; 284 pRSNIEs->abyRSN[2] = 0xAC; 285 if (pMgmt->byCSSGK == KEY_CTL_WEP) 286 pRSNIEs->abyRSN[3] = pMgmt->pCurrBSS->byCSSGK; 287 else if (pMgmt->byCSSGK == KEY_CTL_TKIP) 288 pRSNIEs->abyRSN[3] = WLAN_11i_CSS_TKIP; 289 else if (pMgmt->byCSSGK == KEY_CTL_CCMP) 290 pRSNIEs->abyRSN[3] = WLAN_11i_CSS_CCMP; 291 else 292 pRSNIEs->abyRSN[3] = WLAN_11i_CSS_UNKNOWN; 293 294 // Pairwise Key Cipher Suite 295 pRSNIEs->abyRSN[4] = 1; 296 pRSNIEs->abyRSN[5] = 0; 297 pRSNIEs->abyRSN[6] = 0x00; 298 pRSNIEs->abyRSN[7] = 0x0F; 299 pRSNIEs->abyRSN[8] = 0xAC; 300 if (pMgmt->byCSSPK == KEY_CTL_TKIP) 301 pRSNIEs->abyRSN[9] = WLAN_11i_CSS_TKIP; 302 else if (pMgmt->byCSSPK == KEY_CTL_CCMP) 303 pRSNIEs->abyRSN[9] = WLAN_11i_CSS_CCMP; 304 else if (pMgmt->byCSSPK == KEY_CTL_NONE) 305 pRSNIEs->abyRSN[9] = WLAN_11i_CSS_USE_GROUP; 306 else 307 pRSNIEs->abyRSN[9] = WLAN_11i_CSS_UNKNOWN; 308 309 pRSNIEs->len += 6; 310 311 // Auth Key Management Suite 312 pRSNIEs->abyRSN[10] = 1; 313 pRSNIEs->abyRSN[11] = 0; 314 pRSNIEs->abyRSN[12] = 0x00; 315 pRSNIEs->abyRSN[13] = 0x0F; 316 pRSNIEs->abyRSN[14] = 0xAC; 317 if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK) 318 pRSNIEs->abyRSN[15] = WLAN_11i_AKMSS_PSK; 319 else if (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) 320 pRSNIEs->abyRSN[15] = WLAN_11i_AKMSS_802_1X; 321 else 322 pRSNIEs->abyRSN[15] = WLAN_11i_AKMSS_UNKNOWN; 323 324 pRSNIEs->len += 6; 325 326 // RSN Capabilities 327 if (pMgmt->pCurrBSS->sRSNCapObj.bRSNCapExist == true) { 328 memcpy(&pRSNIEs->abyRSN[16], &pMgmt->pCurrBSS->sRSNCapObj.wRSNCap, 2); 329 } else { 330 pRSNIEs->abyRSN[16] = 0; 331 pRSNIEs->abyRSN[17] = 0; 332 } 333 pRSNIEs->len += 2; 334 335 if ((pMgmt->gsPMKIDCache.BSSIDInfoCount > 0) && 336 pMgmt->bRoaming && 337 (pMgmt->eAuthenMode == WMAC_AUTH_WPA2)) { 338 // RSN PMKID 339 pwPMKID = (unsigned short *)(&pRSNIEs->abyRSN[18]); // Point to PMKID count 340 *pwPMKID = 0; // Initialize PMKID count 341 pbyBuffer = &pRSNIEs->abyRSN[20]; // Point to PMKID list 342 for (ii = 0; ii < pMgmt->gsPMKIDCache.BSSIDInfoCount; ii++) { 343 if (!memcmp(&pMgmt->gsPMKIDCache.BSSIDInfo[ii].abyBSSID[0], pMgmt->abyCurrBSSID, ETH_ALEN)) { 344 (*pwPMKID)++; 345 memcpy(pbyBuffer, pMgmt->gsPMKIDCache.BSSIDInfo[ii].abyPMKID, 16); 346 pbyBuffer += 16; 347 } 348 } 349 if (*pwPMKID != 0) 350 pRSNIEs->len += (2 + (*pwPMKID)*16); 351 else 352 pbyBuffer = &pRSNIEs->abyRSN[18]; 353 } 354 return pRSNIEs->len + WLAN_IEHDR_LEN; 355 } 356 return 0; 357}