[go: nahoru, domu]

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