wpa2.c 12 KB

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