wpa2.c 10 KB

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