Merge tag 'usb-3.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / vt6656 / wpa2.c
CommitLineData
92b96797
FB
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 */
9d26d60f 33
92b96797 34#include "device.h"
11d404cb 35#include "wpa2.h"
92b96797 36
92b96797
FB
37static int msglevel =MSG_LEVEL_INFO;
38//static int msglevel =MSG_LEVEL_DEBUG;
92b96797 39
b902fbfe
AM
40const u8 abyOUIGK[4] = { 0x00, 0x0F, 0xAC, 0x00 };
41const u8 abyOUIWEP40[4] = { 0x00, 0x0F, 0xAC, 0x01 };
42const u8 abyOUIWEP104[4] = { 0x00, 0x0F, 0xAC, 0x05 };
43const u8 abyOUITKIP[4] = { 0x00, 0x0F, 0xAC, 0x02 };
44const u8 abyOUICCMP[4] = { 0x00, 0x0F, 0xAC, 0x04 };
92b96797 45
b902fbfe
AM
46const u8 abyOUI8021X[4] = { 0x00, 0x0F, 0xAC, 0x01 };
47const u8 abyOUIPSK[4] = { 0x00, 0x0F, 0xAC, 0x02 };
92b96797 48
92b96797
FB
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-*/
8611a29a 63void
92b96797 64WPA2_ClearRSN (
592ccfeb 65 PKnownBSS pBSSNode
92b96797
FB
66 )
67{
68 int ii;
69
e269fc2d 70 pBSSNode->bWPA2Valid = false;
92b96797
FB
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;
e269fc2d 79 pBSSNode->sRSNCapObj.bRSNCapExist = false;
92b96797
FB
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-*/
8611a29a 98void
92b96797 99WPA2vParseRSN (
592ccfeb
AM
100 PKnownBSS pBSSNode,
101 PWLAN_IE_RSN pRSN
92b96797
FB
102 )
103{
104 int i, j;
3eaca0d2 105 u16 m = 0, n = 0;
b902fbfe 106 u8 * pbyOUI;
e269fc2d 107 bool bUseGK = false;
92b96797
FB
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)) {
4e9b5e2b 115 pBSSNode->bWPA2Valid = true;
92b96797
FB
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]);
3e362598 132 if ( !memcmp(pbyOUI, abyOUIWEP40, 4))
92b96797 133 pBSSNode->byCSSGK = WLAN_11i_CSS_WEP40;
3e362598 134 else if ( !memcmp(pbyOUI, abyOUITKIP, 4))
92b96797 135 pBSSNode->byCSSGK = WLAN_11i_CSS_TKIP;
3e362598 136 else if ( !memcmp(pbyOUI, abyOUICCMP, 4))
92b96797 137 pBSSNode->byCSSGK = WLAN_11i_CSS_CCMP;
3e362598 138 else if ( !memcmp(pbyOUI, abyOUIWEP104, 4))
92b96797 139 pBSSNode->byCSSGK = WLAN_11i_CSS_WEP104;
3e362598 140 else if ( !memcmp(pbyOUI, abyOUIGK, 4)) {
92b96797
FB
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) {
4e9b5e2b 150 pBSSNode->bWPA2Valid = true;
92b96797
FB
151 return;
152 }
153
154 if (pRSN->len >= 8) { // ver(2) + GK(4) + PK count(2)
3eaca0d2 155 pBSSNode->wCSSPKCount = *((u16 *) &(pRSN->abyRSN[4]));
92b96797
FB
156 j = 0;
157 pbyOUI = &(pRSN->abyRSN[6]);
158
b902fbfe 159 for (i = 0; (i < pBSSNode->wCSSPKCount) && (j < sizeof(pBSSNode->abyCSSPK)/sizeof(u8)); i++) {
92b96797
FB
160
161 if (pRSN->len >= 8+i*4+4) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*i)
3e362598 162 if ( !memcmp(pbyOUI, abyOUIGK, 4)) {
92b96797 163 pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_USE_GROUP;
4e9b5e2b 164 bUseGK = true;
3e362598 165 } else if ( !memcmp(pbyOUI, abyOUIWEP40, 4)) {
a0a1f61a 166 // Invalid CSS, continue parsing
3e362598 167 } else if ( !memcmp(pbyOUI, abyOUITKIP, 4)) {
92b96797
FB
168 if (pBSSNode->byCSSGK != WLAN_11i_CSS_CCMP)
169 pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_TKIP;
170 else
a0a1f61a 171 ; // Invalid CSS, continue parsing
3e362598 172 } else if ( !memcmp(pbyOUI, abyOUICCMP, 4)) {
92b96797 173 pBSSNode->abyCSSPK[j++] = WLAN_11i_CSS_CCMP;
3e362598 174 } else if ( !memcmp(pbyOUI, abyOUIWEP104, 4)) {
a0a1f61a 175 // Invalid CSS, continue parsing
92b96797
FB
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
4e9b5e2b 186 if (bUseGK == true) {
92b96797
FB
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 }
3eaca0d2 200 pBSSNode->wCSSPKCount = (u16)j;
92b96797
FB
201 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wCSSPKCount: %d\n", pBSSNode->wCSSPKCount);
202 }
203
3eaca0d2 204 m = *((u16 *) &(pRSN->abyRSN[4]));
92b96797
FB
205
206 if (pRSN->len >= 10+m*4) { // ver(2) + GK(4) + PK count(2) + PKS(4*m) + AKMSS count(2)
3eaca0d2 207 pBSSNode->wAKMSSAuthCount = *((u16 *) &(pRSN->abyRSN[6+4*m]));
92b96797
FB
208 j = 0;
209 pbyOUI = &(pRSN->abyRSN[8+4*m]);
b902fbfe 210 for (i = 0; (i < pBSSNode->wAKMSSAuthCount) && (j < sizeof(pBSSNode->abyAKMSSAuthType)/sizeof(u8)); i++) {
92b96797 211 if (pRSN->len >= 10+(m+i)*4+4) { // ver(2)+GK(4)+PKCnt(2)+PKS(4*m)+AKMSS(2)+AKS(4*i)
3e362598 212 if ( !memcmp(pbyOUI, abyOUI8021X, 4))
92b96797 213 pBSSNode->abyAKMSSAuthType[j++] = WLAN_11i_AKMSS_802_1X;
3e362598 214 else if ( !memcmp(pbyOUI, abyOUIPSK, 4))
92b96797
FB
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 }
3eaca0d2 223 pBSSNode->wAKMSSAuthCount = (u16)j;
92b96797
FB
224 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"wAKMSSAuthCount: %d\n", pBSSNode->wAKMSSAuthCount);
225
3eaca0d2 226 n = *((u16 *) &(pRSN->abyRSN[6+4*m]));
92b96797 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)
4e9b5e2b 228 pBSSNode->sRSNCapObj.bRSNCapExist = true;
3eaca0d2 229 pBSSNode->sRSNCapObj.wRSNCap = *((u16 *) &(pRSN->abyRSN[8+4*m+4*n]));
92b96797
FB
230 }
231 }
232 //ignore PMKID lists bcs only (Re)Assocrequest has this field
4e9b5e2b 233 pBSSNode->bWPA2Valid = true;
92b96797
FB
234 }
235}