wpa2.c 12 KB

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