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: wpa.c 21 * 22 * Purpose: Handles the Basic Service Set & Node Database functions 23 * 24 * Functions: 25 * WPA_ParseRSN - Parse RSN IE. 26 * 27 * Revision History: 28 * 29 * Author: Kyle Hsu 30 * 31 * Date: July 14, 2003 32 * 33 */ 34 35#include "ttype.h" 36#include "tmacro.h" 37#include "tether.h" 38#include "device.h" 39#include "80211hdr.h" 40#include "bssdb.h" 41#include "wmgr.h" 42#include "wpa.h" 43#include "80211mgr.h" 44 45/*--------------------- Static Variables --------------------------*/ 46static const unsigned char abyOUI00[4] = { 0x00, 0x50, 0xf2, 0x00 }; 47static const unsigned char abyOUI01[4] = { 0x00, 0x50, 0xf2, 0x01 }; 48static const unsigned char abyOUI02[4] = { 0x00, 0x50, 0xf2, 0x02 }; 49static const unsigned char abyOUI03[4] = { 0x00, 0x50, 0xf2, 0x03 }; 50static const unsigned char abyOUI04[4] = { 0x00, 0x50, 0xf2, 0x04 }; 51static const unsigned char abyOUI05[4] = { 0x00, 0x50, 0xf2, 0x05 }; 52 53/*+ 54 * 55 * Description: 56 * Clear RSN information in BSSList. 57 * 58 * Parameters: 59 * In: 60 * pBSSList - BSS list. 61 * Out: 62 * none 63 * 64 * Return Value: none. 65 * 66 -*/ 67 68void 69WPA_ClearRSN( 70 PKnownBSS pBSSList 71) 72{ 73 int ii; 74 75 pBSSList->byGKType = WPA_TKIP; 76 for (ii = 0; ii < 4; ii++) 77 pBSSList->abyPKType[ii] = WPA_TKIP; 78 pBSSList->wPKCount = 0; 79 for (ii = 0; ii < 4; ii++) 80 pBSSList->abyAuthType[ii] = WPA_AUTH_IEEE802_1X; 81 pBSSList->wAuthCount = 0; 82 pBSSList->byDefaultK_as_PK = 0; 83 pBSSList->byReplayIdx = 0; 84 pBSSList->sRSNCapObj.bRSNCapExist = false; 85 pBSSList->sRSNCapObj.wRSNCap = 0; 86 pBSSList->bWPAValid = false; 87} 88 89/*+ 90 * 91 * Description: 92 * Parse RSN IE. 93 * 94 * Parameters: 95 * In: 96 * pBSSList - BSS list. 97 * pRSN - Pointer to the RSN IE. 98 * Out: 99 * none 100 * 101 * Return Value: none. 102 * 103 -*/ 104void 105WPA_ParseRSN( 106 PKnownBSS pBSSList, 107 PWLAN_IE_RSN_EXT pRSN 108) 109{ 110 PWLAN_IE_RSN_AUTH pIE_RSN_Auth = NULL; 111 int i, j, m, n = 0; 112 unsigned char *pbyCaps; 113 114 WPA_ClearRSN(pBSSList); 115 116 pr_debug("WPA_ParseRSN: [%d]\n", pRSN->len); 117 118 // information element header makes sense 119 if ((pRSN->len >= 6) // oui1(4)+ver(2) 120 && (pRSN->byElementID == WLAN_EID_RSN_WPA) && !memcmp(pRSN->abyOUI, abyOUI01, 4) 121 && (pRSN->wVersion == 1)) { 122 pr_debug("Legal RSN\n"); 123 // update each variable if pRSN is long enough to contain the variable 124 if (pRSN->len >= 10) { 125 //OUI1(4)+ver(2)+GKSuite(4) 126 if (!memcmp(pRSN->abyMulticast, abyOUI01, 4)) 127 pBSSList->byGKType = WPA_WEP40; 128 else if (!memcmp(pRSN->abyMulticast, abyOUI02, 4)) 129 pBSSList->byGKType = WPA_TKIP; 130 else if (!memcmp(pRSN->abyMulticast, abyOUI03, 4)) 131 pBSSList->byGKType = WPA_AESWRAP; 132 else if (!memcmp(pRSN->abyMulticast, abyOUI04, 4)) 133 pBSSList->byGKType = WPA_AESCCMP; 134 else if (!memcmp(pRSN->abyMulticast, abyOUI05, 4)) 135 pBSSList->byGKType = WPA_WEP104; 136 else 137 // any vendor checks here 138 pBSSList->byGKType = WPA_NONE; 139 140 pr_debug("byGKType: %x\n", pBSSList->byGKType); 141 } 142 143 if (pRSN->len >= 12) { 144 //oui1(4)+ver(2)+GKS(4)+PKSCnt(2) 145 j = 0; 146 pr_debug("wPKCount: %d, sizeof(pBSSList->abyPKType): %zu\n", 147 pRSN->wPKCount, sizeof(pBSSList->abyPKType)); 148 for (i = 0; (i < pRSN->wPKCount) && (j < ARRAY_SIZE(pBSSList->abyPKType)); i++) { 149 if (pRSN->len >= 12+i*4+4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*i) 150 if (!memcmp(pRSN->PKSList[i].abyOUI, abyOUI00, 4)) 151 pBSSList->abyPKType[j++] = WPA_NONE; 152 else if (!memcmp(pRSN->PKSList[i].abyOUI, abyOUI02, 4)) 153 pBSSList->abyPKType[j++] = WPA_TKIP; 154 else if (!memcmp(pRSN->PKSList[i].abyOUI, abyOUI03, 4)) 155 pBSSList->abyPKType[j++] = WPA_AESWRAP; 156 else if (!memcmp(pRSN->PKSList[i].abyOUI, abyOUI04, 4)) 157 pBSSList->abyPKType[j++] = WPA_AESCCMP; 158 else 159 // any vendor checks here 160 ; 161 } else 162 break; 163 } 164 pBSSList->wPKCount = (unsigned short)j; 165 pr_debug("wPKCount: %d\n", pBSSList->wPKCount); 166 } 167 168 m = pRSN->wPKCount; 169 pr_debug("m: %d\n", m); 170 pr_debug("14+m*4: %d\n", 14+m*4); 171 172 if (pRSN->len >= 14+m*4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*m)+AKC(2) 173 // overlay IE_RSN_Auth structure into correct place 174 pIE_RSN_Auth = (PWLAN_IE_RSN_AUTH) pRSN->PKSList[m].abyOUI; 175 j = 0; 176 pr_debug("wAuthCount: %d, sizeof(pBSSList->abyAuthType): %zu\n", 177 pIE_RSN_Auth->wAuthCount, 178 sizeof(pBSSList->abyAuthType)); 179 for (i = 0; (i < pIE_RSN_Auth->wAuthCount) && (j < ARRAY_SIZE(pBSSList->abyAuthType)); i++) { 180 if (pRSN->len >= 14+4+(m+i)*4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*m)+AKC(2)+AKS(4*i) 181 if (!memcmp(pIE_RSN_Auth->AuthKSList[i].abyOUI, abyOUI01, 4)) 182 pBSSList->abyAuthType[j++] = WPA_AUTH_IEEE802_1X; 183 else if (!memcmp(pIE_RSN_Auth->AuthKSList[i].abyOUI, abyOUI02, 4)) 184 pBSSList->abyAuthType[j++] = WPA_AUTH_PSK; 185 else 186 // any vendor checks here 187 ; 188 } else 189 break; 190 191 } 192 if (j > 0) 193 pBSSList->wAuthCount = (unsigned short)j; 194 pr_debug("wAuthCount: %d\n", pBSSList->wAuthCount); 195 } 196 197 if (pIE_RSN_Auth != NULL) { 198 n = pIE_RSN_Auth->wAuthCount; 199 200 pr_debug("n: %d\n", n); 201 pr_debug("14+4+(m+n)*4: %d\n", 14+4+(m+n)*4); 202 203 if (pRSN->len+2 >= 14+4+(m+n)*4) { //oui1(4)+ver(2)+GKS(4)+PKSCnt(2)+PKS(4*m)+AKC(2)+AKS(4*n)+Cap(2) 204 pbyCaps = (unsigned char *)pIE_RSN_Auth->AuthKSList[n].abyOUI; 205 pBSSList->byDefaultK_as_PK = (*pbyCaps) & WPA_GROUPFLAG; 206 pBSSList->byReplayIdx = 2 << ((*pbyCaps >> WPA_REPLAYBITSSHIFT) & WPA_REPLAYBITS); 207 pBSSList->sRSNCapObj.bRSNCapExist = true; 208 pBSSList->sRSNCapObj.wRSNCap = *(unsigned short *)pbyCaps; 209 } 210 } 211 pBSSList->bWPAValid = true; 212 } 213} 214 215/*+ 216 * 217 * Description: 218 * Search RSN information in BSSList. 219 * 220 * Parameters: 221 * In: 222 * byCmd - Search type 223 * byEncrypt- Encrypt Type 224 * pBSSList - BSS list 225 * Out: 226 * none 227 * 228 * Return Value: none. 229 * 230 -*/ 231bool 232WPA_SearchRSN( 233 unsigned char byCmd, 234 unsigned char byEncrypt, 235 PKnownBSS pBSSList 236) 237{ 238 int ii; 239 unsigned char byPKType = WPA_NONE; 240 241 if (!pBSSList->bWPAValid) 242 return false; 243 244 switch (byCmd) { 245 case 0: 246 247 if (byEncrypt != pBSSList->byGKType) 248 return false; 249 250 if (pBSSList->wPKCount > 0) { 251 for (ii = 0; ii < pBSSList->wPKCount; ii++) { 252 if (pBSSList->abyPKType[ii] == WPA_AESCCMP) 253 byPKType = WPA_AESCCMP; 254 else if ((pBSSList->abyPKType[ii] == WPA_TKIP) && (byPKType != WPA_AESCCMP)) 255 byPKType = WPA_TKIP; 256 else if ((pBSSList->abyPKType[ii] == WPA_WEP40) && (byPKType != WPA_AESCCMP) && (byPKType != WPA_TKIP)) 257 byPKType = WPA_WEP40; 258 else if ((pBSSList->abyPKType[ii] == WPA_WEP104) && (byPKType != WPA_AESCCMP) && (byPKType != WPA_TKIP)) 259 byPKType = WPA_WEP104; 260 } 261 if (byEncrypt != byPKType) 262 return false; 263 } 264 return true; 265 266 default: 267 break; 268 } 269 return false; 270} 271 272/*+ 273 * 274 * Description: 275 * Check if RSN IE makes sense. 276 * 277 * Parameters: 278 * In: 279 * pRSN - Pointer to the RSN IE. 280 * Out: 281 * none 282 * 283 * Return Value: none. 284 * 285 -*/ 286bool 287WPAb_Is_RSN( 288 PWLAN_IE_RSN_EXT pRSN 289) 290{ 291 if (pRSN == NULL) 292 return false; 293 294 if ((pRSN->len >= 6) && // oui1(4)+ver(2) 295 (pRSN->byElementID == WLAN_EID_RSN_WPA) && !memcmp(pRSN->abyOUI, abyOUI01, 4) && 296 (pRSN->wVersion == 1)) { 297 return true; 298 } else 299 return false; 300} 301