| /**************************************************************************** |
| **+-----------------------------------------------------------------------+** |
| **| |** |
| **| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |** |
| **| All rights reserved. |** |
| **| |** |
| **| Redistribution and use in source and binary forms, with or without |** |
| **| modification, are permitted provided that the following conditions |** |
| **| are met: |** |
| **| |** |
| **| * Redistributions of source code must retain the above copyright |** |
| **| notice, this list of conditions and the following disclaimer. |** |
| **| * Redistributions in binary form must reproduce the above copyright |** |
| **| notice, this list of conditions and the following disclaimer in |** |
| **| the documentation and/or other materials provided with the |** |
| **| distribution. |** |
| **| * Neither the name Texas Instruments nor the names of its |** |
| **| contributors may be used to endorse or promote products derived |** |
| **| from this software without specific prior written permission. |** |
| **| |** |
| **| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |** |
| **| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |** |
| **| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |** |
| **| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |** |
| **| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |** |
| **| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |** |
| **| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |** |
| **| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |** |
| **| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |** |
| **| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |** |
| **| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |** |
| **| |** |
| **+-----------------------------------------------------------------------+** |
| ****************************************************************************/ |
| |
| /** \file admCtrlWpa2.c |
| * \brief WPA2 Admission control methods |
| * |
| * \see admCtrl.h |
| */ |
| |
| #include "osApi.h" |
| |
| #include "utils.h" |
| #include "paramOut.h" |
| #include "paramIn.h" |
| #include "mlmeApi.h" |
| #include "802_11Defs.h" |
| #include "DataCtrl_Api.h" |
| #include "report.h" |
| |
| /* |
| #include "fsm.h" |
| #include "utils.h" |
| */ |
| |
| #include "rsn.h" |
| #include "admCtrl.h" |
| #include "admCtrlWpa2.h" |
| #include "osDot11.h" |
| #include "siteMgrApi.h" |
| #include "EvHandler.h" |
| #include "admCtrl.h" |
| |
| #ifdef EXC_MODULE_INCLUDED |
| #include "admCtrlWpa.h" |
| #include "admCtrlExc.h" |
| #include "excMngr.h" |
| #endif |
| |
| /* Constants */ |
| #define MAX_NETWORK_MODE 2 |
| #define MAX_WPA2_CIPHER_SUITE 6 |
| |
| #define PMKID_CAND_LIST_MEMBUFF_SIZE (2*sizeof(UINT32) + (sizeof(OS_802_11_PMKID_CANDIDATE) * PMKID_MAX_NUMBER)) |
| #define PMKID_MIN_BUFFER_SIZE 2*sizeof(UINT32) + MAC_ADDR_LEN + PMKID_VALUE_SIZE |
| |
| #define TI_WLAN_COPY_UINT16_UNALIGNED(addr, val) {\ |
| *((UINT8 *) &(addr)) = (UINT8)(val & 0x00FF); \ |
| *((UINT8 *) &(addr) + 1) = (UINT8)((val & 0xFF00) >> 8);} |
| |
| |
| /* Enumerations */ |
| |
| /* Typedefs */ |
| |
| /* Structures */ |
| |
| /* External data definitions */ |
| |
| /* Local functions definitions */ |
| |
| /* Global variables */ |
| static UINT8 wpa2IeOuiIe[3] = { 0x00, 0x0f, 0xac}; |
| |
| /**************************************************************/ |
| /* reduce stack usage (admCtrlWpa_setSite)*/ |
| /**************************************************************/ |
| static paramInfo_t param; |
| static whalParamInfo_t whalParam; |
| static wpa2IeData_t wpa2DataIE; |
| /**************************************************************/ |
| |
| static BOOL broadcastCipherSuiteValidity[MAX_NETWORK_MODE][MAX_WPA2_CIPHER_SUITE]= |
| { |
| /* RSN_IBSS */ { |
| /* NONE */ FALSE, |
| /* WEP40 */ FALSE, |
| /* TKIP */ TRUE, |
| /* AES_WRAP */ FALSE, |
| /* AES_CCMP */ TRUE, |
| /* WEP104 */ FALSE}, |
| |
| /* RSN_INFRASTRUCTURE */ { |
| /* NONE */ FALSE, |
| /* WEP */ TRUE, |
| /* TKIP */ TRUE, |
| /* AES_WRAP */ FALSE, |
| /* AES_CCMP */ TRUE, |
| /* WEP104 */ TRUE} |
| }; |
| |
| /** WPA2 admission table. Used to verify admission parameters to an AP */ |
| /* table parameters: |
| Max unicast cipher in the IE |
| Max broadcast cipher in the IE |
| Encryption status |
| */ |
| typedef struct |
| { |
| TI_STATUS status; |
| cipherSuite_e unicast; |
| cipherSuite_e broadcast; |
| UINT8 evaluation; |
| } admCtrlWpa2_validity_t; |
| |
| static admCtrlWpa2_validity_t admCtrlWpa2_validityTable[MAX_WPA2_CIPHER_SUITE][MAX_WPA2_CIPHER_SUITE][MAX_WPA2_CIPHER_SUITE] = |
| { |
| /* AP unicast NONE */ { |
| /* AP multicast NONE */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP40 */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WRAP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast WEP40 */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP40 */ { OK, RSN_CIPHER_NONE, RSN_CIPHER_WEP ,1}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WRAP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ OK, RSN_CIPHER_NONE, RSN_CIPHER_WEP104 ,1}}, |
| /* AP multicast TKIP */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { OK, RSN_CIPHER_NONE, RSN_CIPHER_TKIP ,2}, |
| /* STA WRAP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast WRAP */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WRAP */ { OK, RSN_CIPHER_NONE, RSN_CIPHER_AES_WRAP ,3}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast CCMP */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WRAP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { OK, RSN_CIPHER_NONE, RSN_CIPHER_AES_CCMP ,3}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast WEP104 */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP40 */ { OK, RSN_CIPHER_NONE, RSN_CIPHER_WEP ,1}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WRAP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ OK, RSN_CIPHER_NONE, RSN_CIPHER_WEP104 ,1}}}, |
| /* AP unicast WEP */ { |
| /* AP multicast NONE */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WRAP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast WEP */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WRAP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast TKIP */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA AES */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast WRAP */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WRAP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast CCMP */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA AES */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast WEP104 */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA AES */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}}, |
| /* AP unicast TKIP */ { |
| /* AP multicast NONE */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA AES */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast WEP */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { OK, RSN_CIPHER_TKIP, RSN_CIPHER_WEP ,4}, |
| /* STA AES */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast TKIP */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { OK, RSN_CIPHER_TKIP, RSN_CIPHER_TKIP ,7}, |
| /* STA AES */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast WRAP */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA AES */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast CCMP */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA AES */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast WEP104 */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { OK, RSN_CIPHER_TKIP, RSN_CIPHER_WEP104 ,4}, |
| /* STA AES */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}}, |
| /* AP unicast AES_WRAP */ { |
| /* AP multicast NONE */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA AES */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast WEP40 */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA AES */ { OK, RSN_CIPHER_AES_WRAP, RSN_CIPHER_WEP ,5}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast TKIP */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA AES */ { OK, RSN_CIPHER_AES_WRAP, RSN_CIPHER_TKIP ,6}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast WRAP */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA AES */ { OK, RSN_CIPHER_AES_WRAP, RSN_CIPHER_AES_WRAP ,8}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast CCMP */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA AES */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast WEP104 */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA AES */ { OK, RSN_CIPHER_AES_WRAP, RSN_CIPHER_WEP104 ,5}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}}, |
| /* AP unicast AES_CCMP */ { |
| /* AP multicast NONE */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA AES */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast WEP */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA AES */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { OK, RSN_CIPHER_AES_CCMP, RSN_CIPHER_WEP ,5}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast TKIP */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { OK, RSN_CIPHER_AES_CCMP, RSN_CIPHER_TKIP ,6}, |
| /* STA AES */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { OK, RSN_CIPHER_AES_CCMP, RSN_CIPHER_TKIP ,6}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast WRAP */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA AES */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast CCMP */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { OK, RSN_CIPHER_AES_CCMP, RSN_CIPHER_AES_CCMP ,6}, |
| /* STA AES */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { OK, RSN_CIPHER_AES_CCMP, RSN_CIPHER_AES_CCMP ,8}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast WEP */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA AES */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { OK, RSN_CIPHER_AES_CCMP, RSN_CIPHER_WEP104 ,5}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}}, |
| /* AP unicast WEP104 */ { |
| /* AP multicast NONE */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA AES */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast WEP */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA AES */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast TKIP */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA AES */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast WRAP */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA AES */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast CCMP */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA AES */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}, |
| /* AP multicast WEP104 */ { |
| /* STA NONE */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA TKIP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA AES */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA CCMP */ { NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}, |
| /* STA WEP104 */{ NOK, RSN_CIPHER_NONE, RSN_CIPHER_NONE ,0}}} |
| |
| |
| }; |
| |
| |
| /* PMKID cache */ |
| /* static wpa2_pmkid_cache_t wpa2_pmkid_cache; */ |
| |
| /* Function prototypes */ |
| |
| TI_STATUS admCtrlWpa2_parseIe(admCtrl_t *pAdmCtrl, UINT8 *pWpa2Ie, wpa2IeData_t *pWpa2Data); |
| UINT16 admCtrlWpa2_buildCapabilities(admCtrl_t *pAdmCtrl); |
| UINT32 admCtrlWpa2_parseSuiteVal(admCtrl_t *pAdmCtrl, UINT8* suiteVal, UINT32 maxVal, UINT32 unknownVal); |
| TI_STATUS admCtrlWpa2_checkCipherSuiteValidity(cipherSuite_e unicastSuite, cipherSuite_e broadcastSuite, cipherSuite_e encryptionStatus); |
| TI_STATUS admCtrlWpa2_getCipherSuiteMetric (admCtrl_t *pAdmCtrl, wpa2IeData_t *pWpa2Data, UINT32 *metric, |
| cipherSuite_e *uSuite, cipherSuite_e *bSuite); |
| TI_STATUS admCtrlWpa2_DynamicConfig(admCtrl_t *pAdmCtrl, rsn_paeConfig_t *pPaeConfig); |
| |
| TI_STATUS admCtrlWpa2_resetPMKIDCache(admCtrl_t *pAdmCtrl); |
| /*TI_STATUS admCtrlWpa2_sendPMKIDCandListAfterDelay(admCtrl_t * pAdmCtrl, UINT32 delay);*/ |
| TI_STATUS admCtrlWpa2_getPMKIDList(admCtrl_t * pAdmCtrl,OS_802_11_PMKID *pmkidList); |
| TI_STATUS admCtrlWpa2_setPMKIDList(admCtrl_t * pAdmCtrl, OS_802_11_PMKID *pmkidList); |
| |
| TI_STATUS admCtrlWpa2_addPMKID(admCtrl_t * pAdmCtrl, macAddress_t * pBSSID, pmkidValue_t pmkID); |
| TI_STATUS admCtrlWpa2_findPMKID(admCtrl_t * pAdmCtrl, macAddress_t *pBSSID, |
| pmkidValue_t *pPMKID, UINT8 *cacheIndex); |
| |
| static BOOL admCtrlWpa2_getPreAuthStatus(admCtrl_t *pAdmCtrl, macAddress_t *givenAP, UINT8 *cacheIndex); |
| |
| static TI_STATUS admCtrlWpa2_startPreAuth(admCtrl_t *pAdmCtrl, bssidList4PreAuth_t *pBssidList); |
| |
| static void admCtrlWpa2_buildAndSendPMKIDCandList(TI_HANDLE hHandle, bssidList4PreAuth_t *apList); |
| |
| static TI_STATUS admCtrlWpa2_get802_1x_AkmExists (admCtrl_t *pAdmCtrl, BOOL *wpa_802_1x_AkmExists); |
| |
| /** |
| * |
| * admCtrlWpa_config - Configure EXC admission control. |
| * |
| * \b Description: |
| * |
| * Configure EXC admission control. |
| * |
| * \b ARGS: |
| * |
| * I - pAdmCtrl - context \n |
| * |
| * \b RETURNS: |
| * |
| * OK on success, NOK on failure. |
| * |
| * \sa |
| */ |
| TI_STATUS admCtrlWpa2_config(admCtrl_t *pAdmCtrl) |
| { |
| TI_STATUS status; |
| rsn_paeConfig_t paeConfig; |
| |
| /* check and set admission control default parameters */ |
| pAdmCtrl->authSuite = RSN_AUTH_OPEN; |
| if (pAdmCtrl->unicastSuite == RSN_CIPHER_NONE) |
| { |
| pAdmCtrl->unicastSuite = RSN_CIPHER_AES_CCMP; |
| } |
| if (pAdmCtrl->broadcastSuite == RSN_CIPHER_NONE) |
| { |
| pAdmCtrl->broadcastSuite = RSN_CIPHER_AES_CCMP; |
| } |
| |
| /* set callback functions (API) */ |
| pAdmCtrl->getInfoElement = admCtrlWpa2_getInfoElement; |
| pAdmCtrl->setSite = admCtrlWpa2_setSite; |
| pAdmCtrl->evalSite = admCtrlWpa2_evalSite; |
| |
| pAdmCtrl->getPmkidList = admCtrlWpa2_getPMKIDList; |
| pAdmCtrl->setPmkidList = admCtrlWpa2_setPMKIDList; |
| pAdmCtrl->resetPmkidList = admCtrlWpa2_resetPMKIDCache; |
| pAdmCtrl->getPreAuthStatus = admCtrlWpa2_getPreAuthStatus; |
| pAdmCtrl->startPreAuth = admCtrlWpa2_startPreAuth; |
| pAdmCtrl->get802_1x_AkmExists = admCtrlWpa2_get802_1x_AkmExists; |
| |
| /* set key management suite (AKMP) */ |
| switch (pAdmCtrl->externalAuthMode) |
| { |
| case RSN_EXT_AUTH_MODE_WPA2: |
| case RSN_EXT_AUTH_MODE_WPA2PSK: |
| pAdmCtrl->keyMngSuite = RSN_KEY_MNG_802_1X; |
| break; |
| case RSN_EXT_AUTH_MODE_WPANONE: |
| pAdmCtrl->keyMngSuite = RSN_KEY_MNG_NONE; |
| /* Not supported */ |
| default: |
| return NOK; |
| } |
| |
| |
| paeConfig.authProtocol = pAdmCtrl->externalAuthMode; |
| paeConfig.unicastSuite = pAdmCtrl->unicastSuite; |
| paeConfig.broadcastSuite = pAdmCtrl->broadcastSuite; |
| paeConfig.keyExchangeProtocol = pAdmCtrl->keyMngSuite; |
| /* set default PAE configuration */ |
| status = pAdmCtrl->pRsn->setPaeConfig(pAdmCtrl->pRsn, &paeConfig); |
| |
| return status; |
| } |
| |
| |
| /** |
| * |
| * admCtrlWpa2_getInfoElement - Get the current information element. |
| * |
| * \b Description: |
| * |
| * Get the current information element. |
| * |
| * \b ARGS: |
| * |
| * I - pAdmCtrl - context \n |
| * I - pIe - IE buffer \n |
| * I - pLength - length of IE \n |
| * |
| * \b RETURNS: |
| * |
| * OK on success, NOK on failure. |
| * |
| * \sa |
| */ |
| |
| TI_STATUS admCtrlWpa2_getInfoElement(admCtrl_t *pAdmCtrl, UINT8 *pIe, UINT8 *pLength) |
| { |
| wpa2IePacket_t *pWpa2IePacket; |
| UINT8 length = 0; |
| macAddress_t assocBssid; |
| paramInfo_t param; |
| pmkidValue_t pmkId; |
| TI_STATUS status; |
| UINT8 index; |
| |
| #ifdef FOUR_ALIGNMENT |
| UINT16 tempInt; |
| #endif |
| |
| if (pIe==NULL) |
| { |
| *pLength = 0; |
| return NOK; |
| } |
| |
| /* check Group suite validity */ |
| if (!broadcastCipherSuiteValidity[pAdmCtrl->networkMode][pAdmCtrl->broadcastSuite]) |
| { |
| *pLength = 0; |
| return NOK; |
| } |
| |
| /* Init Wpa2 IE (RSN IE) */ |
| pWpa2IePacket = (wpa2IePacket_t*)pIe; |
| os_memoryZero(pAdmCtrl->hOs, pWpa2IePacket, sizeof(wpa2IePacket_t)); |
| |
| |
| /* Fill the element ID */ |
| pWpa2IePacket->elementid = RSN_IE_ID; |
| |
| |
| #ifndef FOUR_ALIGNMENT |
| pWpa2IePacket->version = ENDIAN_HANDLE_WORD(WPA2_OUI_MAX_VERSION); |
| #else |
| /* required for WinCe, when the pointer is not even */ |
| tempInt = ENDIAN_HANDLE_WORD(WPA2_OUI_MAX_VERSION); |
| os_memoryCopy(pAdmCtrl->hOs, (UINT8 *)&pWpa2IePacket->version, &tempInt, sizeof(pWpa2IePacket->version)); |
| #endif |
| length += 2; |
| |
| /* build group suite */ |
| os_memoryCopy(pAdmCtrl->hOs, (void *)pWpa2IePacket->groupSuite, wpa2IeOuiIe, 3); |
| pWpa2IePacket->groupSuite[3] = (UINT8)pAdmCtrl->pRsn->paeConfig.broadcastSuite; |
| length += 4; |
| |
| /* build pairwise suite - we always send only one pairwise suite */ |
| #ifndef FOUR_ALIGNMENT |
| pWpa2IePacket->pairwiseSuiteCnt = ENDIAN_HANDLE_WORD(0x0001); |
| #else |
| /* required for WinCe, when the pointer is not even */ |
| tempInt = ENDIAN_HANDLE_WORD(0x0001); |
| os_memoryCopy(pAdmCtrl->hOs, (UINT8 *)&pWpa2IePacket->pairwiseSuiteCnt, &tempInt, sizeof(pWpa2IePacket->pairwiseSuiteCnt)); |
| #endif |
| |
| length += 2; |
| |
| os_memoryCopy(pAdmCtrl->hOs, (void *)pWpa2IePacket->pairwiseSuite, wpa2IeOuiIe, 3); |
| pWpa2IePacket->pairwiseSuite[3] = (UINT8)pAdmCtrl->pRsn->paeConfig.unicastSuite; |
| length += 4; |
| |
| |
| /* build keyMng suite - we always send only one key mgmt suite*/ |
| #ifndef FOUR_ALIGNMENT |
| pWpa2IePacket->authKeyMngSuiteCnt = ENDIAN_HANDLE_WORD(0x0001); |
| #else |
| /* required for WinCe, when the pointer is not even */ |
| tempInt = ENDIAN_HANDLE_WORD(0x0001); |
| os_memoryCopy(pAdmCtrl->hOs, (UINT8 *)&pWpa2IePacket->authKeyMngSuiteCnt, &tempInt, sizeof(pWpa2IePacket->authKeyMngSuiteCnt)); |
| #endif |
| |
| length += 2; |
| |
| os_memoryCopy(pAdmCtrl->hOs, (void *)pWpa2IePacket->authKeyMngSuite, wpa2IeOuiIe, 3); |
| |
| switch (pAdmCtrl->externalAuthMode) |
| { |
| case RSN_EXT_AUTH_MODE_OPEN: |
| case RSN_EXT_AUTH_MODE_SHARED_KEY: |
| case RSN_EXT_AUTH_MODE_AUTO_SWITCH: |
| pWpa2IePacket->authKeyMngSuite[3] = WPA2_IE_KEY_MNG_NONE; |
| break; |
| case RSN_EXT_AUTH_MODE_WPA2: |
| case RSN_EXT_AUTH_MODE_WPA: /* for Any-WPA/WPA-Mixed mode */ |
| { |
| #ifdef EXC_MODULE_INCLUDED |
| UINT8 akmSuite[DOT11_OUI_LEN+1]; |
| |
| if (admCtrlExc_getCckmAkm(pAdmCtrl, akmSuite)) |
| { |
| os_memoryCopy(pAdmCtrl->hOs, (PVOID)pWpa2IePacket->authKeyMngSuite, akmSuite, DOT11_OUI_LEN+1); |
| } |
| else |
| #endif |
| { |
| pWpa2IePacket->authKeyMngSuite[3] = WPA2_IE_KEY_MNG_801_1X; |
| } |
| } |
| break; |
| case RSN_EXT_AUTH_MODE_WPA2PSK: |
| case RSN_EXT_AUTH_MODE_WPAPSK: |
| pWpa2IePacket->authKeyMngSuite[3] = WPA2_IE_KEY_MNG_PSK_801_1X; |
| break; |
| default: |
| pWpa2IePacket->authKeyMngSuite[3] = WPA2_IE_KEY_MNG_NONE; |
| break; |
| } |
| |
| length += 4; |
| |
| /* build Capabilities */ |
| #ifndef FOUR_ALIGNMENT |
| pWpa2IePacket->capabilities = ENDIAN_HANDLE_WORD(admCtrlWpa2_buildCapabilities(pAdmCtrl)); |
| #else |
| /* required for WinCe, when the pointer is not even */ |
| tempInt = ENDIAN_HANDLE_WORD(admCtrlWpa2_buildCapabilities(pAdmCtrl)); |
| os_memoryCopy(pAdmCtrl->hOs, (UINT8 *)&pWpa2IePacket->capabilities, &tempInt, sizeof(pWpa2IePacket->capabilities)); |
| #endif |
| |
| length += 2; |
| |
| /* build PMKID list: we support no more than 1 PMKSA per AP, */ |
| /* so no more than 1 PMKID can be sent in the RSN IE */ |
| if(pAdmCtrl->preAuthSupport && |
| (pAdmCtrl->pRsn->paeConfig.authProtocol == RSN_EXT_AUTH_MODE_WPA2)) |
| { |
| /* Init value of PMKID count is 0 */ |
| #ifndef FOUR_ALIGNMENT |
| pWpa2IePacket->pmkIdCnt = ENDIAN_HANDLE_WORD(0); |
| #else |
| /* required for WinCe, when the pointer is not even */ |
| tempInt = ENDIAN_HANDLE_WORD(0); |
| os_memoryCopy(pAdmCtrl->hOs, (UINT8 *)&pWpa2IePacket->pmkIdCnt, &tempInt, sizeof(pWpa2IePacket->pmkIdCnt)); |
| #endif |
| |
| length += 2; |
| |
| param.paramType = CTRL_DATA_CURRENT_BSSID_PARAM; |
| status = ctrlData_getParam(pAdmCtrl->pRsn->hCtrlData, ¶m); |
| |
| assocBssid = param.content.ctrlDataCurrentBSSID; |
| |
| WLAN_REPORT_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("admCtrlWpa2_getInfoElement - find PMKID \n")); |
| |
| status = admCtrlWpa2_findPMKID(pAdmCtrl, &assocBssid, &pmkId, &index); |
| if(status == OK) |
| { |
| WLAN_REPORT_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("admCtrlWpa2_getInfoElement - PMKID was found! \n")); |
| |
| #ifndef FOUR_ALIGNMENT |
| pWpa2IePacket->pmkIdCnt = ENDIAN_HANDLE_WORD(1); |
| #else |
| /* required for WinCe, when the pointer is not even */ |
| tempInt = ENDIAN_HANDLE_WORD(1); |
| os_memoryCopy(pAdmCtrl->hOs, (UINT8 *)&pWpa2IePacket->pmkIdCnt, &tempInt, sizeof(pWpa2IePacket->pmkIdCnt)); |
| #endif |
| |
| os_memoryCopy(pAdmCtrl->hOs, (UINT8 *)pWpa2IePacket->pmkId, |
| (UINT8 *)pmkId, PMKID_VALUE_SIZE); |
| |
| length += PMKID_VALUE_SIZE; |
| } |
| } |
| |
| pWpa2IePacket->length = length; /* RSN IE length without IEid and length field */ |
| *pLength = length+2; /* The whole length of the RSN IE */ |
| |
| WLAN_REPORT_HEX_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| pIe, *pLength); |
| return OK; |
| |
| } |
| /** |
| * |
| * admCtrlWpa2_setSite - Set current primary site parameters for registration. |
| * |
| * \b Description: |
| * |
| * Set current primary site parameters for registration. |
| * |
| * \b ARGS: |
| * |
| * I - pAdmCtrl - context \n |
| * I - pRsnData - site's RSN data \n |
| * O - pAssocIe - result IE of evaluation \n |
| * O - pAssocIeLen - length of result IE of evaluation \n |
| * |
| * \b RETURNS: |
| * |
| * OK on site is aproved, NOK on site is rejected. |
| * |
| * \sa |
| */ |
| TI_STATUS admCtrlWpa2_setSite(admCtrl_t *pAdmCtrl, rsnData_t *pRsnData, UINT8 *pAssocIe, UINT8 *pAssocIeLen) |
| { |
| TI_STATUS status; |
| rsn_paeConfig_t paeConfig; |
| UINT8 *pWpa2Ie; |
| cipherSuite_e uSuite, bSuite; |
| |
| |
| *pAssocIeLen = 0; |
| |
| if (pRsnData==NULL) |
| { |
| return NOK; |
| } |
| if (pRsnData->pIe==NULL) |
| { |
| /* configure the MLME module with the 802.11 OPEN authentication suite, |
| THe MLME will configure later the authentication module */ |
| param.paramType = MLME_LEGACY_TYPE_PARAM; |
| param.content.mlmeLegacyAuthType = AUTH_LEGACY_OPEN_SYSTEM; |
| status = mlme_setParam(pAdmCtrl->hMlme, ¶m); |
| if (status != OK) |
| { |
| return status; |
| } |
| |
| return OK; |
| } |
| |
| #ifdef EXC_MODULE_INCLUDED |
| /* Clean MIC and KP flags in the HAL. */ |
| /* It is needed if the previous privacy mode was EXC */ |
| whalParam.paramType = HAL_CTRL_RSN_EXC_SW_ENC_ENABLE_PARAM; |
| whalParam.content.rsnExcSwEncFlag = FALSE; |
| status = whalCtrl_SetParam(pAdmCtrl->pRsn->hWhalCtrl, &whalParam); |
| |
| whalParam.paramType = HAL_CTRL_RSN_EXC_MIC_FIELD_ENABLE_PARAM; |
| whalParam.content.rsnExcMicFieldFlag = FALSE; |
| status = whalCtrl_SetParam(pAdmCtrl->pRsn->hWhalCtrl, &whalParam); |
| |
| /* Check if Aironet IE exists */ |
| admCtrlExc_setExtendedParams(pAdmCtrl, pRsnData); |
| |
| #endif /*EXC_MODULE_INCLUDED*/ |
| |
| status = admCtrl_parseIe(pAdmCtrl, pRsnData, &pWpa2Ie, RSN_IE_ID); |
| if (status != OK) |
| { |
| return status; |
| } |
| WLAN_REPORT_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("admCtrlWpa2_setSite: RSN_IE=\n")); |
| WLAN_REPORT_HEX_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, pRsnData->pIe, pRsnData->ieLen); |
| status = admCtrlWpa2_parseIe(pAdmCtrl, pWpa2Ie, &wpa2DataIE); |
| if (status != OK) |
| { |
| return status; |
| } |
| if ((wpa2DataIE.unicastSuite[0]>=MAX_WPA2_CIPHER_SUITE) || |
| (wpa2DataIE.broadcastSuite>=MAX_WPA2_CIPHER_SUITE) || |
| (pAdmCtrl->unicastSuite>=MAX_WPA2_CIPHER_SUITE)) |
| { |
| return NOK; |
| } |
| /* Check validity of Group suite */ |
| if (!broadcastCipherSuiteValidity[pAdmCtrl->networkMode][wpa2DataIE.broadcastSuite]) |
| { /* check Group suite validity */ |
| return NOK; |
| } |
| |
| |
| if(admCtrlWpa2_getCipherSuiteMetric (pAdmCtrl, &wpa2DataIE, NULL, &uSuite, &bSuite) != OK) |
| return NOK; |
| |
| /* set replay counter */ |
| pAdmCtrl->replayCnt = wpa2DataIE.ptkReplayCounters; |
| |
| *pAssocIeLen = pRsnData->ieLen; |
| if (pAssocIe != NULL) |
| { |
| os_memoryCopy(pAdmCtrl->hOs, pAssocIe, &wpa2DataIE, sizeof(wpa2IeData_t)); |
| } |
| |
| /* re-config PAE with updated unicast and broadcast suite values */ |
| /* If STA works in WpaMixed mode/AnyWpa mode, set PAE auth. mode to WPA2 */ |
| paeConfig.authProtocol = pAdmCtrl->externalAuthMode; |
| |
| if(pAdmCtrl->WPAPromoteFlags) |
| { |
| if(pAdmCtrl->externalAuthMode == RSN_EXT_AUTH_MODE_WPA) |
| paeConfig.authProtocol = RSN_EXT_AUTH_MODE_WPA2; |
| if(pAdmCtrl->externalAuthMode == RSN_EXT_AUTH_MODE_WPAPSK) |
| paeConfig.authProtocol = RSN_EXT_AUTH_MODE_WPA2PSK; |
| } |
| |
| |
| #ifdef EXC_MODULE_INCLUDED |
| param.paramType = EXC_CCKM_EXISTS; |
| param.content.excCckmExists = (wpa2Data.KeyMngSuite[0]==WPA2_IE_KEY_MNG_CCKM) ? TRUE : FALSE; |
| excMngr_setParam(pAdmCtrl->hExcMngr, ¶m); |
| #endif |
| |
| |
| paeConfig.keyExchangeProtocol = pAdmCtrl->keyMngSuite; |
| paeConfig.unicastSuite = uSuite; /* Updated value */ |
| paeConfig.broadcastSuite = bSuite; /* Updated value */ |
| status = admCtrlWpa2_DynamicConfig(pAdmCtrl, &paeConfig); |
| |
| if (status != OK) |
| { |
| return status; |
| } |
| |
| /* Now we configure the MLME module with the 802.11 legacy authentication suite, |
| THe MLME will configure later the authentication module */ |
| param.paramType = MLME_LEGACY_TYPE_PARAM; |
| #ifdef EXC_MODULE_INCLUDED |
| if (pAdmCtrl->networkEapMode!=OS_EXC_NETWORK_EAP_OFF) |
| { |
| param.content.mlmeLegacyAuthType = AUTH_LEGACY_RESERVED1; |
| } |
| else |
| #endif |
| { |
| param.content.mlmeLegacyAuthType = AUTH_LEGACY_OPEN_SYSTEM; |
| } |
| status = mlme_setParam(pAdmCtrl->hMlme, ¶m); |
| if (status != OK) |
| { |
| return status; |
| } |
| |
| param.paramType = RX_DATA_EAPOL_DESTINATION_PARAM; |
| param.content.rxDataEapolDestination = OS_ABS_LAYER; |
| status = rxData_setParam(pAdmCtrl->hRx, ¶m); |
| if (status != OK) |
| { |
| return status; |
| } |
| |
| /* Configure privacy status in HAL so that HW is prepared to recieve keys */ |
| whalParam.paramType = HAL_CTRL_RSN_SECURITY_MODE_PARAM; |
| whalParam.content.rsnEncryptionStatus = (halCtrl_CipherSuite_e)paeConfig.unicastSuite; |
| status = whalCtrl_SetParam(pAdmCtrl->pRsn->hWhalCtrl, &whalParam); |
| |
| return status; |
| } |
| |
| /** |
| * |
| * admCtrlWpa_evalSite - Evaluate site for registration. |
| * |
| * \b Description: |
| * |
| * evaluate site RSN capabilities against the station's cap. |
| * If the BSS type is infrastructure, the station matches the site only if it's WEP status is same as the site |
| * In IBSS, it does not matter |
| * |
| * \b ARGS: |
| * |
| * I - pAdmCtrl - Context \n |
| * I - pRsnData - site's RSN data \n |
| * O - pEvaluation - Result of evaluation \n |
| * |
| * \b RETURNS: |
| * |
| * OK |
| * |
| * \sa |
| */ |
| TI_STATUS admCtrlWpa2_evalSite(admCtrl_t *pAdmCtrl, rsnData_t *pRsnData, bssType_e bssType, UINT32 *pEvaluation) |
| { |
| TI_STATUS status; |
| wpa2IeData_t wpa2Data; |
| UINT8 *pWpa2Ie; |
| cipherSuite_e uSuite, bSuite; |
| UINT8 i = 0; |
| |
| |
| *pEvaluation = 0; |
| |
| if (pRsnData==NULL) |
| { |
| return NOK; |
| } |
| if (pRsnData->pIe==NULL) |
| { |
| return NOK; |
| } |
| |
| if (bssType != BSS_INFRASTRUCTURE) |
| { |
| return NOK; |
| } |
| |
| status = admCtrl_parseIe(pAdmCtrl, pRsnData, &pWpa2Ie, RSN_IE_ID); |
| if (status != OK) |
| { |
| return status; |
| } |
| WLAN_REPORT_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("admCtrlWpa2_evalSite, IE=\n")); |
| |
| WLAN_REPORT_HEX_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, pRsnData->pIe, pRsnData->ieLen); |
| |
| status = admCtrlWpa2_parseIe(pAdmCtrl, pWpa2Ie, &wpa2Data); |
| if (status != OK) |
| { |
| return status; |
| } |
| |
| /* check keyMngSuite validity */ |
| status = NOK; |
| for(i = 0; |
| (i < wpa2Data.KeyMngSuiteCnt) &&(i<MAX_WPA2_KEY_MNG_SUITES)&& (status != OK); |
| i++) |
| { |
| switch (wpa2Data.KeyMngSuite[i]) |
| { |
| case WPA2_IE_KEY_MNG_NONE: |
| status = (pAdmCtrl->externalAuthMode <= RSN_EXT_AUTH_MODE_AUTO_SWITCH) ? OK : NOK; |
| break; |
| case WPA2_IE_KEY_MNG_801_1X: |
| #ifdef EXC_MODULE_INCLUDED |
| case WPA2_IE_KEY_MNG_CCKM: |
| /* CCKM is allowed only in 802.1x auth */ |
| #endif |
| |
| if(!pAdmCtrl->WPAPromoteFlags) |
| status = (pAdmCtrl->externalAuthMode == RSN_EXT_AUTH_MODE_WPA2) ? OK : NOK; |
| else |
| /* Any-WPA mode is supported */ |
| status = ((pAdmCtrl->externalAuthMode == RSN_EXT_AUTH_MODE_WPA2) || |
| (pAdmCtrl->externalAuthMode == RSN_EXT_AUTH_MODE_WPA)) ? OK : NOK; |
| break; |
| case WPA2_IE_KEY_MNG_PSK_801_1X: |
| if(!pAdmCtrl->WPAPromoteFlags) |
| status = (pAdmCtrl->externalAuthMode == RSN_EXT_AUTH_MODE_WPA2PSK) ? OK : NOK; |
| else |
| /* Any-WPA mode is supported */ |
| status = ((pAdmCtrl->externalAuthMode == RSN_EXT_AUTH_MODE_WPA2PSK) || |
| (pAdmCtrl->externalAuthMode == RSN_EXT_AUTH_MODE_WPAPSK)) ? OK : NOK; |
| break; |
| default: |
| WLAN_REPORT_ERROR(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("admCtrlWpa2_evalSite, default, wpa2Data.KeyMngSuite[i]=%d \n",wpa2Data.KeyMngSuite[i])); |
| status = NOK; |
| break; |
| } |
| } |
| |
| if (status != OK) |
| { |
| WLAN_REPORT_ERROR(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("admCtrlWpa2_evalSite, status=%d, externalAuthMode=%d, WPAPromoteFlags=%d \n", |
| status, pAdmCtrl->externalAuthMode, |
| pAdmCtrl->WPAPromoteFlags)); |
| return status; |
| } |
| |
| /* Check cipher suite validity */ |
| if(admCtrlWpa2_getCipherSuiteMetric(pAdmCtrl, &wpa2Data, pEvaluation, &uSuite, &bSuite) != OK) |
| return NOK; |
| |
| /* Check privacy bit if not in mixed mode */ |
| if (!pAdmCtrl->mixedMode) |
| { /* There's no mixed mode, so make sure that the privacy Bit matches the privacy mode*/ |
| if (((pRsnData->privacy) && (uSuite == RSN_CIPHER_NONE)) || |
| ((!pRsnData->privacy) && (uSuite > RSN_CIPHER_NONE))) |
| { |
| *pEvaluation = 0; |
| WLAN_REPORT_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("admCtrlWpa2_evalSite, mixedMode is FALSE, privacy=%d, uSuite=%d\n", |
| pRsnData->privacy, uSuite)); |
| return NOK; |
| } |
| } |
| |
| /* always return OK */ |
| return OK; |
| } |
| |
| |
| /** |
| * |
| * admCtrlWpa2_parseIe - Parse an WPA information element. |
| * |
| * \b Description: |
| * |
| * Parse an WPA information element. |
| * Builds a structure of the unicast adn broadcast cihper suites, |
| * the key management suite and the capabilities. |
| * |
| * \b ARGS: |
| * |
| * I - pAdmCtrl - pointer to admCtrl context |
| * I - pWpa2Ie - pointer to WPA IE (RSN IE) buffer \n |
| * O - pWpa2Data - WPA2 IE (RSN IE) structure after parsing |
| * |
| * |
| * \b RETURNS: |
| * |
| * OK on success, NOK on failure. |
| * |
| * \sa |
| */ |
| TI_STATUS admCtrlWpa2_parseIe(admCtrl_t *pAdmCtrl, UINT8 *pWpa2Ie, wpa2IeData_t *pWpa2Data) |
| { |
| dot11_RSN_t *wpa2Ie = (dot11_RSN_t *)pWpa2Ie; |
| UINT16 temp2bytes, capabilities; |
| UINT16 KeyMngSuiteCntTemp=0; |
| UINT8 dataOffset = 0, i = 0, j = 0, curKeyMngSuite = 0; |
| cipherSuite_e curCipherSuite = RSN_CIPHER_NONE; |
| |
| WLAN_REPORT_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("Wpa2_IE: DEBUG: admCtrlWpa2_parseIe\n\n")); |
| |
| if ((pWpa2Data == NULL) || (pWpa2Ie == NULL)) |
| { |
| return NOK; |
| } |
| |
| /* get Version value from the info element */ |
| temp2bytes = ENDIAN_HANDLE_WORD(*wpa2Ie->rsnIeData); |
| dataOffset += 2; |
| |
| /* Check the header fields and the version */ |
| if((wpa2Ie->hdr.eleId != RSN_IE_ID) || (wpa2Ie->hdr.eleLen < WPA2_IE_MIN_LENGTH) || |
| (temp2bytes != WPA2_OUI_MAX_VERSION)) |
| { |
| WLAN_REPORT_ERROR(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("Wpa2_ParseIe Error: length=0x%x, elementid=0x%x, version=0x%x\n", |
| wpa2Ie->hdr.eleLen,wpa2Ie->hdr.eleId,temp2bytes)); |
| |
| return NOK; |
| } |
| |
| |
| /* Set default values */ |
| os_memoryZero(pAdmCtrl->hOs, pWpa2Data, sizeof(wpa2IeData_t)); |
| |
| pWpa2Data->broadcastSuite = RSN_CIPHER_AES_CCMP; |
| pWpa2Data->unicastSuiteCnt = 1; |
| pWpa2Data->unicastSuite[0] = RSN_CIPHER_AES_CCMP; |
| pWpa2Data->KeyMngSuiteCnt = 1; |
| pWpa2Data->KeyMngSuite[0] = WPA2_IE_KEY_MNG_801_1X; |
| |
| /* If we've reached the end of the received RSN IE */ |
| if(wpa2Ie->hdr.eleLen < WPA2_IE_GROUP_SUITE_LENGTH) |
| return OK; |
| |
| /* Processing of Group Suite field - 4 bytes*/ |
| pWpa2Data->broadcastSuite = (cipherSuite_e)admCtrlWpa2_parseSuiteVal(pAdmCtrl, (UINT8 *)wpa2Ie->rsnIeData + dataOffset, |
| RSN_CIPHER_WEP104, RSN_CIPHER_UNKNOWN); |
| dataOffset +=4; |
| WLAN_REPORT_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("Wpa2_IE: GroupSuite %x \n", pWpa2Data->broadcastSuite)); |
| |
| |
| /* Processing of Pairwise (Unicast) Cipher Suite - 2 bytes counter and list of 4-byte entries */ |
| if(wpa2Ie->hdr.eleLen < WPA2_IE_MIN_PAIRWISE_SUITE_LENGTH) |
| return OK; |
| |
| pWpa2Data->unicastSuiteCnt = ENDIAN_HANDLE_WORD(*(wpa2Ie->rsnIeData + dataOffset)); |
| dataOffset += 2; |
| |
| if(pWpa2Data->unicastSuiteCnt > UNICAST_CIPHER_MAXNO_IN_RSNIE) |
| { |
| /* something wrong in the RSN IE */ |
| WLAN_REPORT_ERROR(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("Wpa2_ParseIe Error: Pairwise cipher suite count is %d \n", pWpa2Data->unicastSuiteCnt)); |
| return NOK; |
| } |
| |
| /* Get unicast cipher suites */ |
| for(i = 0; i < pWpa2Data->unicastSuiteCnt; i++) |
| { |
| curCipherSuite = (cipherSuite_e)admCtrlWpa2_parseSuiteVal(pAdmCtrl, (UINT8 *)wpa2Ie->rsnIeData + dataOffset, |
| RSN_CIPHER_WEP104, RSN_CIPHER_UNKNOWN); |
| if(curCipherSuite == RSN_CIPHER_NONE) |
| curCipherSuite = pWpa2Data->broadcastSuite; |
| |
| pWpa2Data->unicastSuite[i] = curCipherSuite; |
| dataOffset +=4; |
| |
| WLAN_REPORT_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("Wpa_IE: unicast suite %x \n", curCipherSuite)); |
| } |
| |
| /* Sort all the unicast suites supported by the AP in the decreasing order */ |
| /* (so the best cipher suite will be the first) */ |
| if(pWpa2Data->unicastSuiteCnt > 1) |
| { |
| for(i = 0; i < (pWpa2Data->unicastSuiteCnt -1); i ++) |
| { |
| for(j = 0; j < i; j ++) |
| { |
| if(pWpa2Data->unicastSuite[j] > pWpa2Data->unicastSuite[j + 1]) |
| { |
| curCipherSuite = pWpa2Data->unicastSuite[j]; |
| pWpa2Data->unicastSuite[j] = pWpa2Data->unicastSuite[j+1]; |
| pWpa2Data->unicastSuite[j+1] = curCipherSuite; |
| } |
| } |
| } |
| } |
| |
| /* If we've reached the end of the received RSN IE */ |
| if (wpa2Ie->hdr.eleLen == dataOffset) |
| return OK; |
| |
| /* KeyMng Suite */ |
| /* pWpa2Data->KeyMngSuiteCnt = ENDIAN_HANDLE_WORD(*((UINT16 *)(wpa2Ie->rsnIeData + dataOffset))); */ |
| |
| /*Fixing unaligned half word access */ |
| |
| COPY_UNALIGNED_WORD(&KeyMngSuiteCntTemp,((UINT16 *)(wpa2Ie->rsnIeData + dataOffset))); |
| KeyMngSuiteCntTemp = ENDIAN_HANDLE_WORD(KeyMngSuiteCntTemp); |
| TI_WLAN_COPY_UINT16_UNALIGNED(pWpa2Data->KeyMngSuiteCnt, KeyMngSuiteCntTemp); |
| |
| |
| dataOffset += 2; |
| pAdmCtrl->wpaAkmExists = FALSE; |
| for(i = 0; i < pWpa2Data->KeyMngSuiteCnt; i++) |
| { |
| #ifdef EXC_MODULE_INCLUDED |
| curKeyMngSuite = admCtrlExc_parseCckmSuiteVal4Wpa2(pAdmCtrl, (UINT8 *)(wpa2Ie->rsnIeData + dataOffset)); |
| if (curKeyMngSuite == WPA2_IE_KEY_MNG_CCKM) |
| { /* CCKM is the maximum AKM */ |
| pWpa2Data->KeyMngSuite[i] = curKeyMngSuite; |
| } |
| else |
| #endif |
| { |
| curKeyMngSuite = admCtrlWpa2_parseSuiteVal(pAdmCtrl, (UINT8 *)wpa2Ie->rsnIeData + dataOffset, |
| WPA2_IE_KEY_MNG_PSK_801_1X, WPA2_IE_KEY_MNG_NA); |
| } |
| |
| |
| WLAN_REPORT_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("Wpa2_IE: authKeyMng %x \n", curKeyMngSuite)); |
| |
| if ((curKeyMngSuite != WPA2_IE_KEY_MNG_NA) && |
| (curKeyMngSuite != WPA2_IE_KEY_MNG_CCKM)) |
| { |
| pWpa2Data->KeyMngSuite[i] = curKeyMngSuite; |
| } |
| |
| if (curKeyMngSuite==WPA2_IE_KEY_MNG_801_1X) |
| { /* If 2 AKM exist, save also the second priority */ |
| pAdmCtrl->wpaAkmExists = TRUE; |
| } |
| |
| dataOffset += 4; |
| } |
| |
| /* If we've reached the end of the received RSN IE */ |
| if (wpa2Ie->hdr.eleLen == dataOffset) |
| return OK; |
| |
| /* Parse capabilities */ |
| |
| /* capabilities = ENDIAN_HANDLE_WORD(*((UINT16 *)(wpa2Ie->rsnIeData + dataOffset))); */ |
| |
| /* Fixing unaligned half word access */ |
| |
| COPY_UNALIGNED_WORD(&capabilities,((UINT16 *)(wpa2Ie->rsnIeData + dataOffset))); |
| capabilities = ENDIAN_HANDLE_WORD(capabilities); |
| |
| |
| pWpa2Data->bcastForUnicatst = (UINT8)(capabilities & WPA2_GROUP_4_UNICAST_CAPABILITY_MASK)>> |
| WPA2_GROUP_4_UNICAST_CAPABILITY_SHIFT; |
| pWpa2Data->ptkReplayCounters = (UINT8)(capabilities & WPA2_PTK_REPLAY_COUNTERS_CAPABILITY_MASK)>> |
| WPA2_PTK_REPLAY_COUNTERS_CAPABILITY_SHIFT; |
| |
| switch (pWpa2Data->ptkReplayCounters) |
| { |
| case 0: pWpa2Data->ptkReplayCounters=1; |
| break; |
| case 1: pWpa2Data->ptkReplayCounters=2; |
| break; |
| case 2: pWpa2Data->ptkReplayCounters=4; |
| break; |
| case 3: pWpa2Data->ptkReplayCounters=16; |
| break; |
| default: pWpa2Data->ptkReplayCounters=1; |
| break; |
| } |
| pWpa2Data->gtkReplayCounters = (UINT8)(capabilities & |
| WPA2_GTK_REPLAY_COUNTERS_CAPABILITY_MASK) >> |
| WPA2_GTK_REPLAY_COUNTERS_CAPABILITY_SHIFT; |
| switch (pWpa2Data->gtkReplayCounters) |
| { |
| case 0: pWpa2Data->gtkReplayCounters=1; |
| break; |
| case 1: pWpa2Data->gtkReplayCounters=2; |
| break; |
| case 2: pWpa2Data->gtkReplayCounters=4; |
| break; |
| case 3: pWpa2Data->gtkReplayCounters=16; |
| break; |
| default: pWpa2Data->gtkReplayCounters=1; |
| break; |
| } |
| |
| pWpa2Data->preAuthentication = (UINT8)(capabilities & WPA2_PRE_AUTH_CAPABILITY_MASK); |
| |
| WLAN_REPORT_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("Wpa2_IE: capabilities %x, preAuthentication = %x, bcastForUnicatst %x, ptk = %x, gtk = %x\n", |
| capabilities, pWpa2Data->preAuthentication, |
| pWpa2Data->bcastForUnicatst, pWpa2Data->ptkReplayCounters, |
| pWpa2Data->gtkReplayCounters)); |
| |
| return OK; |
| |
| } |
| |
| |
| UINT16 admCtrlWpa2_buildCapabilities(admCtrl_t *pAdmCtrl) |
| { |
| UINT16 capabilities = 0; |
| UINT16 replayCnt; |
| |
| |
| /* Bit 0 - Pre-authentication is set to 0 */ |
| /* when RSN IE is sent from a STA (in assoc request) */ |
| |
| /* Bit1: group key for unicast is set to 0*/ |
| |
| /* Bits 2&3: PTKSA Replay counter; bits 4&5 GTKSA replay Counters */ |
| switch (pAdmCtrl->replayCnt) |
| { |
| case 1: replayCnt=0; |
| break; |
| case 2: replayCnt=1; |
| break; |
| case 4: replayCnt=2; |
| break; |
| case 16: replayCnt=3; |
| break; |
| default: replayCnt=0; |
| break; |
| } |
| |
| capabilities |= replayCnt << WPA2_PTK_REPLAY_COUNTERS_CAPABILITY_SHIFT; |
| capabilities |= replayCnt << WPA2_GTK_REPLAY_COUNTERS_CAPABILITY_SHIFT; |
| |
| return capabilities; |
| |
| } |
| |
| |
| UINT32 admCtrlWpa2_parseSuiteVal(admCtrl_t *pAdmCtrl, UINT8* suiteVal, UINT32 maxVal, UINT32 unknownVal) |
| { |
| UINT32 suite; |
| |
| if ((pAdmCtrl==NULL) || (suiteVal==NULL)) |
| { |
| return RSN_CIPHER_UNKNOWN; |
| } |
| if (!os_memoryCompare(pAdmCtrl->hOs, suiteVal, wpa2IeOuiIe, 3)) |
| { |
| suite = (cipherSuite_e)((suiteVal[3]<=maxVal) ? suiteVal[3] : unknownVal); |
| } else |
| { |
| suite = unknownVal; |
| } |
| return suite; |
| |
| } |
| |
| |
| TI_STATUS admCtrlWpa2_checkCipherSuiteValidity (cipherSuite_e unicastSuite, cipherSuite_e broadcastSuite, cipherSuite_e encryptionStatus) |
| { |
| cipherSuite_e maxCipher; |
| |
| maxCipher = (unicastSuite>=broadcastSuite) ? unicastSuite : broadcastSuite ; |
| if (maxCipher != encryptionStatus) |
| { |
| return NOK; |
| } |
| if ((unicastSuite != RSN_CIPHER_NONE) && (broadcastSuite>unicastSuite)) |
| { |
| return NOK; |
| } |
| return OK; |
| } |
| |
| TI_STATUS admCtrlWpa2_getCipherSuiteMetric (admCtrl_t *pAdmCtrl, wpa2IeData_t *pWpa2Data, UINT32 *metric, |
| cipherSuite_e *uSuite, cipherSuite_e *bSuite) |
| { |
| cipherSuite_e encryption = RSN_CIPHER_NONE; |
| cipherSuite_e unicastSuite = RSN_CIPHER_NONE, brdcstSuite = RSN_CIPHER_NONE; |
| admCtrlWpa2_validity_t admCtrlWpa2_validity; |
| UINT32 maxMetric = 0, index = 0; |
| TI_STATUS status = NOK; |
| |
| /* Set admCtrlWpa2_validity initial values */ |
| admCtrlWpa2_validity = admCtrlWpa2_validityTable[RSN_CIPHER_NONE][RSN_CIPHER_NONE][RSN_CIPHER_NONE]; |
| |
| /* Check validity of configured encryption (cipher) and validity of */ |
| /* promoted cipher (in case of AnyWPA (WPAmixed mode)) */ |
| pAdmCtrl->getCipherSuite(pAdmCtrl, &encryption); |
| WLAN_REPORT_INFORMATION (pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("admCtrlWpa2_getCipherSuiteMetric, encryption=%d\n", encryption)); |
| |
| while(encryption != RSN_CIPHER_NONE) |
| { |
| for (index=0; index<pWpa2Data->unicastSuiteCnt; index++) |
| { |
| admCtrlWpa2_validity = |
| admCtrlWpa2_validityTable[pWpa2Data->unicastSuite[index]][pWpa2Data->broadcastSuite][encryption]; |
| if (admCtrlWpa2_validity.status == OK) |
| { |
| WLAN_REPORT_INFORMATION (pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("admCtrlWpa2_getCipherSuiteMetric, break: validity.evaluation=%d\n", |
| admCtrlWpa2_validity.evaluation)); |
| break; |
| } |
| } |
| |
| if ((admCtrlWpa2_validity.status == OK) && (admCtrlWpa2_validity.evaluation > maxMetric)) |
| { |
| WLAN_REPORT_INFORMATION (pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("admCtrlWpa2_getCipherSuiteMetric, validity.evaluation=%d, maxMetric=%d\n", |
| admCtrlWpa2_validity.evaluation, maxMetric)); |
| |
| maxMetric = admCtrlWpa2_validity.evaluation; |
| status = admCtrlWpa2_validity.status; |
| unicastSuite = admCtrlWpa2_validity.unicast; |
| brdcstSuite = admCtrlWpa2_validity.broadcast; |
| } |
| |
| if((pAdmCtrl->WPAPromoteFlags & ADMCTRL_WPA_OPTION_ENABLE_PROMOTE_CIPHER) && |
| (encryption != RSN_CIPHER_AES_CCMP)) |
| encryption = RSN_CIPHER_AES_CCMP; |
| else |
| encryption = RSN_CIPHER_NONE; |
| |
| } /* End of "while encryption" stmt */ |
| |
| if(metric) |
| *metric = maxMetric; |
| |
| if(uSuite) |
| *uSuite = unicastSuite; |
| |
| if(bSuite) |
| *bSuite = brdcstSuite; |
| |
| return status; |
| } |
| |
| |
| /** |
| * |
| * admCtrlWpa2_DynamicConfig - Dynamic setting of WPA2 config parameters. |
| * |
| * \b Description: |
| * |
| * Sets WPA2 callback procedures and PAE configuration parameters. |
| * This procedure is similar to admCtrlWpa2_Config procedure. |
| * The main difference is that admCtrlWpa2_Config sets the DEFAULT VALUES |
| * of the configuration parameters and so it should be called during |
| * initialization of the driver code or when Auth mode or Encryption status |
| * parameters are beeing set. |
| * admCtrlWpa2_DynamicConfig set the updated values of WPA2 configuration |
| * parameters which gets after negotiation with an AP. So the procedure |
| * should be called during setSite stage. |
| * |
| * \b ARGS: |
| * |
| * I - pAdmCtrl - pointer to admCtrl context |
| * I - pPaeConfig - pointer to PAE structure |
| * |
| * \b RETURNS: |
| * |
| * OK on success, NOK on failure. |
| * |
| * \sa |
| */ |
| |
| TI_STATUS admCtrlWpa2_DynamicConfig(admCtrl_t *pAdmCtrl, rsn_paeConfig_t *pPaeConfig) |
| { |
| TI_STATUS status = OK; |
| |
| /* Set those WPA2 params and callback procedures used after setSite stage */ |
| pAdmCtrl->getInfoElement = admCtrlWpa2_getInfoElement; |
| |
| pAdmCtrl->getPmkidList = admCtrlWpa2_getPMKIDList; |
| pAdmCtrl->setPmkidList = admCtrlWpa2_setPMKIDList; |
| pAdmCtrl->resetPmkidList = admCtrlWpa2_resetPMKIDCache; |
| pAdmCtrl->getPreAuthStatus = admCtrlWpa2_getPreAuthStatus; |
| pAdmCtrl->startPreAuth = admCtrlWpa2_startPreAuth; |
| |
| /* set key management suite */ |
| switch (pAdmCtrl->externalAuthMode) |
| { |
| case RSN_EXT_AUTH_MODE_WPA2: |
| case RSN_EXT_AUTH_MODE_WPA2PSK: |
| pAdmCtrl->keyMngSuite = RSN_KEY_MNG_802_1X; |
| break; |
| case RSN_EXT_AUTH_MODE_WPA: /* It is any-WPA (WPA-mixed mode ) */ |
| case RSN_EXT_AUTH_MODE_WPAPSK: |
| pAdmCtrl->keyMngSuite = RSN_KEY_MNG_802_1X; |
| break; |
| case RSN_EXT_AUTH_MODE_WPANONE: |
| pAdmCtrl->keyMngSuite = RSN_KEY_MNG_NONE; |
| /* Not supported */ |
| default: |
| return NOK; |
| } |
| |
| /* Config PAE (if needed) */ |
| if(pPaeConfig) |
| status = pAdmCtrl->pRsn->setPaeConfig(pAdmCtrl->pRsn, pPaeConfig); |
| |
| return status; |
| } |
| |
| |
| |
| |
| /** |
| * |
| * admCtrlWpa2_findPMKID |
| * |
| * \b Description: |
| * |
| * Retrieve an AP's PMKID (if exist) |
| |
| * \b ARGS: |
| * |
| * I - pAdmCtrl - pointer to admCtrl context |
| * I - pBSSID - pointer to AP's BSSID address |
| * O - pmkID - pointer to AP's PMKID (if it is NULL ptr, only |
| * cache index will be returned to the caller) |
| * O - cacheIndex - index of the cache table entry containing the |
| bssid |
| * |
| * \b RETURNS: |
| * |
| * OK on success, NOK on failure. |
| * |
| * \sa |
| */ |
| TI_STATUS admCtrlWpa2_findPMKID (admCtrl_t * pAdmCtrl, macAddress_t *pBSSID, |
| pmkidValue_t *pPMKID, UINT8 *cacheIndex) |
| { |
| |
| UINT8 i = 0; |
| BOOL found = FALSE; |
| macAddress_t entryMac; |
| TI_STATUS status = NOK; |
| |
| while(!found && (i < ADMCTRL_PMKID_CACHE_SIZE) && |
| (i <= pAdmCtrl->pmkid_cache.entriesNumber)) |
| { |
| entryMac = pAdmCtrl->pmkid_cache.pmkidTbl[i].bssId; |
| if(MAC_EQUAL ((&entryMac),pBSSID)) |
| { |
| found = TRUE; |
| *cacheIndex = i; |
| if(pPMKID) |
| { |
| os_memoryCopy(pAdmCtrl->hOs, (PVOID)pPMKID, |
| pAdmCtrl->pmkid_cache.pmkidTbl[i].pmkId, |
| PMKID_VALUE_SIZE); |
| } |
| } |
| i++; |
| } |
| |
| if(found) |
| status = OK; |
| |
| return status; |
| |
| } |
| |
| |
| /** |
| * |
| * admCtrlWpa2_getPMKIDList |
| * |
| * \b Description: |
| * |
| * Returns content of the PMKID cache |
| * |
| * \b ARGS: |
| * |
| * I - pAdmCtrl - pointer to admCtrl context |
| * O - pmkidList - memory buffer where the procedure writes the PMKIDs |
| * Supplied by the caller procedure. . |
| * |
| * \b RETURNS: |
| * |
| * OK on success, NOK on failure. |
| * |
| * \sa |
| */ |
| TI_STATUS admCtrlWpa2_getPMKIDList (admCtrl_t * pAdmCtrl,OS_802_11_PMKID *pmkidList) |
| { |
| |
| UINT8 neededLength, i = 0; |
| UINT8 NumOfEntries = pAdmCtrl->pmkid_cache.entriesNumber; |
| UINT8 *bssid, *pmkid; |
| |
| if(!pAdmCtrl->preAuthSupport) |
| return PARAM_NOT_SUPPORTED; |
| |
| /* Check the buffer length */ |
| if(NumOfEntries > 1) |
| neededLength = 30 + ((NumOfEntries - 1) * (MAC_ADDR_LEN + PMKID_VALUE_SIZE)); |
| else |
| neededLength = 30; |
| |
| if(neededLength > pmkidList->Length) |
| { |
| /* The buffer length is not enough */ |
| pmkidList->Length = neededLength; |
| return NOK; |
| } |
| |
| /* The buffer is big enough. Fill the info */ |
| pmkidList->Length = neededLength; |
| pmkidList->BSSIDInfoCount = NumOfEntries; |
| |
| WLAN_REPORT_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("RSN: Get PMKID cache. Number of entries = %d \n", NumOfEntries)); |
| |
| for (i = 0; i < NumOfEntries; i++ ) |
| { |
| bssid = (UINT8 *) pAdmCtrl->pmkid_cache.pmkidTbl[i].bssId.addr; |
| pmkid = (UINT8 *)pAdmCtrl->pmkid_cache.pmkidTbl[i].pmkId; |
| |
| os_memoryCopy(pAdmCtrl->hOs, (void *)pmkidList->osBSSIDInfo[i].BSSID, |
| &bssid, MAC_ADDR_LEN); |
| |
| os_memoryCopy(pAdmCtrl->hOs,(void *)pmkidList->osBSSIDInfo[i].PMKID, |
| &pmkid, PMKID_VALUE_SIZE); |
| |
| WLAN_REPORT_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("RSN: BSSID: %.2X-%.2X-%.2X-%.2X-%.2X-%.2X PMKID: %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X \n", |
| bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5], |
| pmkid[0], pmkid[1], pmkid[2], pmkid[3], |
| pmkid[4], pmkid[5], pmkid[6], pmkid[7], |
| pmkid[8], pmkid[9], pmkid[10],pmkid[11], |
| pmkid[12],pmkid[13],pmkid[14],pmkid[15])); |
| } |
| |
| return OK; |
| |
| } |
| |
| /** |
| * |
| * admCtrlWpa2_addPMKID |
| * |
| * \b Description: |
| * |
| * Add/Set an AP's PMKID received from the Supplicant |
| * |
| * \b ARGS: |
| * |
| * I - pAdmCtrl - pointer to admCtrl context |
| * I - pBSSID - pointer to AP's BSSID address |
| * I - pmkID - AP's PMKID |
| * |
| * \b RETURNS: |
| * |
| * OK on success, NOK on failure. |
| * |
| * \sa |
| */ |
| TI_STATUS admCtrlWpa2_addPMKID (admCtrl_t * pAdmCtrl, macAddress_t *pBSSID, pmkidValue_t pmkID) |
| { |
| UINT8 cacheIndex; |
| TI_STATUS status = NOK; |
| |
| /* Try to find the pBSSId in the PMKID cache */ |
| status = admCtrlWpa2_findPMKID (pAdmCtrl, pBSSID, NULL, &cacheIndex); |
| |
| if(status == OK) |
| { |
| /* Entry for the bssid has been found; Update PMKID */ |
| os_memoryCopy(pAdmCtrl->hOs, |
| (PVOID)&pAdmCtrl->pmkid_cache.pmkidTbl[cacheIndex].pmkId, |
| pmkID, PMKID_VALUE_SIZE); |
| /*pAdmCtrl->pmkid_cache.pmkidTbl[cacheIndex].generationTs = os_timeStampMs(pAdmCtrl->hOs); */ |
| } |
| else |
| { |
| /* The new entry is added to the next free entry. */ |
| /* Copy the new entry to the next free place. */ |
| cacheIndex = pAdmCtrl->pmkid_cache.nextFreeEntry; |
| os_memoryCopy(pAdmCtrl->hOs, |
| (PVOID)&pAdmCtrl->pmkid_cache.pmkidTbl[cacheIndex].bssId.addr, |
| &(pBSSID->addr), MAC_ADDR_LEN); |
| os_memoryCopy(pAdmCtrl->hOs, |
| (PVOID)&pAdmCtrl->pmkid_cache.pmkidTbl[cacheIndex].pmkId, |
| (PVOID)pmkID, PMKID_VALUE_SIZE); |
| |
| /* Update the next free entry index. (If the table is full, a new entry */ |
| /* will override the oldest entries from the beginning of the table) */ |
| /* Update the number of entries. (it cannot be more than max cach size) */ |
| pAdmCtrl->pmkid_cache.nextFreeEntry = (cacheIndex + 1) % ADMCTRL_PMKID_CACHE_SIZE; |
| |
| if(pAdmCtrl->pmkid_cache.entriesNumber < ADMCTRL_PMKID_CACHE_SIZE) |
| pAdmCtrl->pmkid_cache.entriesNumber ++; |
| } |
| |
| WLAN_REPORT_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("RSN Add PMKID Entry index is %d \n", cacheIndex)); |
| WLAN_REPORT_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("RSN: BSSID: %.2X-%.2X-%.2X-%.2X-%.2X-%.2X PMKID: %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X \n", |
| pBSSID->addr[0], pBSSID->addr[1], pBSSID->addr[2], |
| pBSSID->addr[3], pBSSID->addr[4], pBSSID->addr[5], |
| pmkID[0], pmkID[1], pmkID[2], pmkID[3], |
| pmkID[4], pmkID[5], pmkID[6], pmkID[7], |
| pmkID[8], pmkID[9], pmkID[10],pmkID[11], |
| pmkID[12],pmkID[13],pmkID[14],pmkID[15])); |
| |
| |
| |
| return OK; |
| } |
| |
| /** |
| * |
| * admCtrlWpa2_setPMKIDList |
| * |
| * \b Description: |
| * |
| * Set PMKID cache |
| * |
| * \b ARGS: |
| * |
| * I - pAdmCtrl - pointer to admCtrl context |
| * O - pmkidList - memory buffer where the procedure reads the PMKIDs from |
| * Supplied by the caller procedure. |
| * \b RETURNS: |
| * |
| * OK on success, NOK on failure. |
| * |
| * \sa |
| */ |
| TI_STATUS admCtrlWpa2_setPMKIDList (admCtrl_t * pAdmCtrl, OS_802_11_PMKID *pmkidList) |
| { |
| UINT8 neededLength, i = 0; |
| UINT8 NumOfEntries; |
| macAddress_t macAddr; |
| |
| /* Check the minimal buffer length */ |
| if (pmkidList->Length < 2*sizeof(UINT32)) |
| { |
| WLAN_REPORT_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("RSN: Set PMKID list - Buffer size < min length (8 bytes). Supplied length is %d .\n", |
| pmkidList->Length)); |
| return NOK; |
| } |
| |
| /* Check the num of entries in the buffer: if 0 it means that */ |
| /* PMKID cache has to be cleaned */ |
| if(pmkidList->BSSIDInfoCount == 0) |
| { |
| admCtrlWpa2_resetPMKIDCache(pAdmCtrl); |
| return OK; |
| } |
| |
| /* Check the buffer length */ |
| NumOfEntries = (UINT8)pmkidList->BSSIDInfoCount; |
| neededLength = 2*sizeof(UINT32) + (NumOfEntries *(MAC_ADDR_LEN + PMKID_VALUE_SIZE)); |
| |
| if(pmkidList->Length < neededLength) |
| { |
| /* Something wrong goes with the buffer */ |
| WLAN_REPORT_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("RSN: Set PMKID list - no enough room for %d entries; Needed length is %d. Supplied length is %d .\n", |
| NumOfEntries, neededLength,pmkidList->Length)); |
| return NOK; |
| } |
| |
| /* Write the PMKID to the PMKID cashe */ |
| pmkidList->BSSIDInfoCount = NumOfEntries; |
| for (i = 0; i < NumOfEntries; i++ ) |
| { |
| os_memoryCopy(pAdmCtrl->hOs, &macAddr.addr, |
| &(pmkidList->osBSSIDInfo[i].BSSID), MAC_ADDR_LEN); |
| WLAN_REPORT_INFORMATION (pAdmCtrl->hReport, RSN_MODULE_LOG,("admCtrlWpa2_setPMKIDList: Received new pre-auth AP\n")); |
| if (pAdmCtrl->numberOfPreAuthCandidates) |
| { |
| pAdmCtrl->numberOfPreAuthCandidates--; |
| if (pAdmCtrl->numberOfPreAuthCandidates == 0) |
| { |
| WLAN_REPORT_INFORMATION (pAdmCtrl->hReport, RSN_MODULE_LOG,("Stopping the Pre-Auth timer since Pre-auth is finished\n")); |
| os_timerStop(pAdmCtrl->hOs, pAdmCtrl->preAuthTimerWpa2); |
| /* Send PRE-AUTH end event to External Application */ |
| admCtrl_notifyPreAuthStatus (pAdmCtrl, RSN_PRE_AUTH_END); |
| } |
| |
| WLAN_REPORT_INFORMATION (pAdmCtrl->hReport, RSN_MODULE_LOG,("admCtrlWpa2_setPMKIDList: %d APs left in candidate list\n",pAdmCtrl->numberOfPreAuthCandidates)); |
| |
| } |
| else |
| { |
| WLAN_REPORT_WARNING (pAdmCtrl->hReport, RSN_MODULE_LOG,("admCtrlWpa2_setPMKIDList: number of candidates was already zero...\n")); |
| } |
| admCtrlWpa2_addPMKID(pAdmCtrl,&macAddr, (UINT8 *)pmkidList->osBSSIDInfo[i].PMKID); |
| } |
| |
| return OK; |
| |
| } |
| |
| /** |
| * |
| * admCtrlWpa2_resetPMKIDCache |
| * |
| * \b Description: |
| * |
| * Reset PMKID Table |
| * |
| * \b ARGS: |
| * |
| * I - pAdmCtrl - pointer to admCtrl context |
| * |
| * \b RETURNS: |
| * |
| * OK on success, NOK on failure. |
| * |
| * \sa |
| */ |
| TI_STATUS admCtrlWpa2_resetPMKIDCache (admCtrl_t *pAdmCtrl) |
| { |
| |
| WLAN_REPORT_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("RSN: Reset PMKID cache. %d entries are deleted. \n", |
| pAdmCtrl->pmkid_cache.entriesNumber)); |
| |
| os_memoryZero(pAdmCtrl->hOs, (PVOID)&pAdmCtrl->pmkid_cache, sizeof(pmkid_cache_t)); |
| |
| return OK; |
| } |
| |
| |
| /** |
| * |
| * admCtrlWpa2_sendPMKIDCandidateListAfterDelay |
| * |
| * \b Description: |
| * |
| * New Candidate List of APs with the same SSID as the STA is connected to |
| * is generated and sent after the delay to the supplicant |
| * in order to retrieve the new PMKIDs for the APs. |
| * |
| * \b ARGS: |
| * I - pAdmCtrl - pointer to admCtrl context |
| * |
| * \b RETURNS: |
| * |
| * OK on success, NOK on failure. |
| * |
| * \sa |
| */ |
| |
| static void admCtrlWpa2_buildAndSendPMKIDCandList (TI_HANDLE hHandle, bssidList4PreAuth_t *apList) |
| { |
| |
| admCtrl_t *pAdmCtrl = (admCtrl_t *)hHandle; |
| UINT8 candIndex =0, apIndex = 0, size =0; |
| paramInfo_t param; |
| OS_802_11_PMKID_CANDIDATELIST *pCandList; |
| UINT8 memBuff[PMKID_CAND_LIST_MEMBUFF_SIZE + sizeof(UINT32)]; |
| dot11_RSN_t *rsnIE = 0; |
| wpa2IeData_t wpa2Data; |
| TI_STATUS status = NOK; |
| |
| /* Get SSID that the STA is accociated with */ |
| param.paramType = SITE_MGR_DESIRED_SSID_PARAM; |
| status = siteMgr_getParam(pAdmCtrl->pRsn->hSiteMgr, ¶m); |
| if(status != OK) |
| return; |
| |
| /* If the existing PMKID cache contains information for not relevant */ |
| /* ssid (i.e. ssid was changed), clean up the PMKID cache and update */ |
| /* the ssid in the PMKID cache */ |
| if ((pAdmCtrl->pmkid_cache.ssid.len != param.content.siteMgrDesiredSSID.len) || |
| (os_memoryCompare(pAdmCtrl->hOs, (UINT8 *)pAdmCtrl->pmkid_cache.ssid.ssidString, |
| (UINT8 *) param.content.siteMgrCurrentSSID.ssidString, |
| pAdmCtrl->pmkid_cache.ssid.len) != 0)) |
| { |
| admCtrlWpa2_resetPMKIDCache(pAdmCtrl); |
| |
| os_memoryCopy(pAdmCtrl->hOs, (void *)pAdmCtrl->pmkid_cache.ssid.ssidString, |
| (void *)param.content.siteMgrCurrentSSID.ssidString, |
| param.content.siteMgrCurrentSSID.len); |
| pAdmCtrl->pmkid_cache.ssid.len = param.content.siteMgrCurrentSSID.len; |
| } |
| |
| /* Get list of APs of the SSID that the STA is associated with*/ |
| /*os_memoryZero(pAdmCtrl->hOs, (PVOID)&apList, sizeof(bssidListBySsid_t)); |
| status = siteMgr_GetApListBySsid (pAdmCtrl->pRsn->hSiteMgr, |
| ¶m.content.siteMgrCurrentSSID, |
| &apList); |
| */ |
| if((apList == NULL) || (apList->NumOfItems == 0)) |
| return; |
| |
| WLAN_REPORT_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("admCtrlWpa2_buildAndSendPMKIDCandList - Entry \n")); |
| |
| /* fill the PMKID candidate list */ |
| pCandList = (OS_802_11_PMKID_CANDIDATELIST *)(memBuff + sizeof(UINT32)); |
| pCandList->Version = 1; |
| for (apIndex=0; apIndex<pAdmCtrl->pmkid_cache.entriesNumber; apIndex++) |
| { |
| pAdmCtrl->pmkid_cache.pmkidTbl[apIndex].preAuthenticate = FALSE; |
| } |
| |
| /* Go over AP list and find APs supporting pre-authentication */ |
| for(apIndex = 0; apIndex < apList->NumOfItems; apIndex++) |
| { |
| UINT8 *bssidMac, i = 0; |
| |
| status = NOK; |
| |
| if (apList->bssidList[apIndex].pRsnIEs==NULL) |
| { |
| continue; |
| } |
| /* Check is there RSN IE in this site */ |
| rsnIE = 0; |
| while( !rsnIE && (i < MAX_RSN_IE)) |
| { |
| if(apList->bssidList[apIndex].pRsnIEs[i].hdr.eleId == RSN_IE_ID) |
| { |
| rsnIE = &apList->bssidList[apIndex].pRsnIEs[i]; |
| status = OK; |
| } |
| i ++; |
| } |
| WLAN_REPORT_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("admCtrlWpa2_buildAndSendPMKIDCandList - rsnIE-hdr.eleId = %x \n", rsnIE->hdr.eleId)); |
| |
| if(status == OK) |
| status = admCtrlWpa2_parseIe(pAdmCtrl, (UINT8 *)rsnIE, &wpa2Data); |
| |
| WLAN_REPORT_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("admCtrlWpa2_buildAndSendPMKIDCandList - parseIe status = %d \n", status)); |
| if(status == OK) |
| { |
| BOOL preAuthStatus; |
| UINT8 cacheIndex; |
| |
| preAuthStatus = admCtrlWpa2_getPreAuthStatus(pAdmCtrl, &apList->bssidList[apIndex].bssId, &cacheIndex); |
| |
| WLAN_REPORT_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("admCtrlWpa2_buildAndSendPMKIDCandList, preAuthStatus=%d \n", |
| preAuthStatus)); |
| |
| if (preAuthStatus) |
| { |
| pAdmCtrl->pmkid_cache.pmkidTbl[cacheIndex].preAuthenticate = TRUE; |
| } |
| |
| bssidMac = (UINT8 *)apList->bssidList[apIndex].bssId.addr; |
| os_memoryCopy(pAdmCtrl->hOs, &(pCandList->CandidateList[candIndex].BSSID), |
| bssidMac, MAC_ADDR_LEN); |
| |
| if(pAdmCtrl->preAuthSupport && (wpa2Data.preAuthentication)) |
| { |
| pCandList->CandidateList[candIndex].Flags = |
| OS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLE; |
| } |
| else |
| { |
| pCandList->CandidateList[candIndex].Flags = 0; |
| |
| } |
| |
| WLAN_REPORT_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("RSN: Candidate [%d] is %.2X-%.2X-%.2X-%.2X-%.2X-%.2X , Flags=0x%x\n", candIndex, |
| bssidMac[0], bssidMac[1], bssidMac[2], |
| bssidMac[3], bssidMac[4], bssidMac[5], |
| pCandList->CandidateList[candIndex].Flags)); |
| |
| candIndex ++; |
| } |
| |
| } |
| /* Add candidates that have valid PMKID, but were not in the list */ |
| for (apIndex=0; apIndex<pAdmCtrl->pmkid_cache.entriesNumber; apIndex++) |
| { |
| if (!pAdmCtrl->pmkid_cache.pmkidTbl[apIndex].preAuthenticate) |
| { |
| os_memoryCopy(pAdmCtrl->hOs, &(pCandList->CandidateList[candIndex].BSSID), |
| (void *)pAdmCtrl->pmkid_cache.pmkidTbl[apIndex].bssId.addr, MAC_ADDR_LEN); |
| pCandList->CandidateList[apIndex].Flags = |
| OS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLE; |
| candIndex++; |
| } |
| } |
| |
| |
| pCandList->NumCandidates = candIndex; |
| |
| |
| /* Send Status Media specific indication to OS */ |
| size = sizeof(OS_802_11_PMKID_CANDIDATELIST) + |
| (candIndex - 1) * sizeof(OS_802_11_PMKID_CANDIDATE) + sizeof(UINT32); |
| |
| /* Fill type of indication */ |
| *(UINT32*)memBuff = os802_11StatusType_PMKID_CandidateList; |
| |
| pCandList->NumCandidates = candIndex; |
| |
| /* Store the number of candidates sent - needed for pre-auth finish event */ |
| pAdmCtrl->numberOfPreAuthCandidates = candIndex; |
| /* Start the pre-authentication finish event timer */ |
| /* If the pre-authentication process is not over by the time it expires - we send an event */ |
| WLAN_REPORT_INFORMATION (pAdmCtrl->hReport, RSN_MODULE_LOG,("Starting PREAUTH timer (%d mSec)\n",pAdmCtrl->preAuthTimeout*candIndex)); |
| |
| os_timerStart(pAdmCtrl->hOs, pAdmCtrl->preAuthTimerWpa2, pAdmCtrl->preAuthTimeout*candIndex, FALSE); |
| EvHandlerSendEvent(pAdmCtrl->hEvHandler, IPC_EVENT_MEDIA_SPECIFIC, |
| memBuff, size); |
| |
| /* Send PRE-AUTH start event to External Application */ |
| admCtrl_notifyPreAuthStatus (pAdmCtrl, RSN_PRE_AUTH_START); |
| WLAN_REPORT_INFORMATION(pAdmCtrl->hReport, RSN_MODULE_LOG, |
| ("RSN: PMKID Candidate List with %d entries has been built and sent for ssid %s \n", |
| candIndex, pAdmCtrl->pmkid_cache.ssid.ssidString)); |
| |
| |
| return; |
| |
| } |
| |
| /** |
| * |
| * admCtrlWpa2_getPreAuthStatus |
| * |
| * \b Description: |
| * |
| * Returns the status of the Pre Auth for the BSSID. If the authentictaion mode |
| * is not WPA2, then FALSE will be returned. |
| * For WPA2 mode, if PMKID exists fro the BSSID and its liftime is valid |
| * TRUE will be returned. |
| * Otherwise FALSE. |
| * |
| * |
| * |
| * \b ARGS: |
| * I - pAdmCtrl - pointer to admCtrl context |
| * I - givenAP - required BSSID |
| * |
| * \b RETURNS: |
| * |
| * OK on success, NOK on failure. |
| * |
| * \sa |
| */ |
| static BOOL admCtrlWpa2_getPreAuthStatus(admCtrl_t *pAdmCtrl, macAddress_t *givenAP, UINT8 *cacheIndex) |
| { |
| pmkidValue_t PMKID; |
| |
| if (admCtrlWpa2_findPMKID (pAdmCtrl, givenAP, |
| &PMKID, cacheIndex)!=OK) |
| { |
| return FALSE; |
| } |
| return TRUE; |
| |
| } |
| |
| static TI_STATUS admCtrlWpa2_startPreAuth(admCtrl_t *pAdmCtrl, bssidList4PreAuth_t *pBssidList) |
| { |
| |
| admCtrlWpa2_buildAndSendPMKIDCandList (pAdmCtrl, pBssidList); |
| return OK; |
| } |
| |
| static TI_STATUS admCtrlWpa2_get802_1x_AkmExists (admCtrl_t *pAdmCtrl, BOOL *wpa_802_1x_AkmExists) |
| { |
| *wpa_802_1x_AkmExists = pAdmCtrl->wpaAkmExists; |
| return OK; |
| } |
| |
| |
| |
| /*----------------------------------------------------------------------------- |
| Routine Name: admCtrlWpa2_preAuthTimerExpire |
| Routine Description: updates the preAuthStatus |
| Arguments: |
| Return Value: |
| -----------------------------------------------------------------------------*/ |
| void admCtrlWpa2_preAuthTimerExpire(TI_HANDLE hAdmCtrl) |
| { |
| admCtrl_t *pAdmCtrl = (admCtrl_t *)hAdmCtrl; |
| WLAN_REPORT_WARNING (pAdmCtrl->hReport, RSN_MODULE_LOG,("admCtrlWpa2_preAuthTimerExpire: PREAUTH EXPIRED !!!!!!!!")); |
| /* Send PRE-AUTH end event to External Application */ |
| admCtrl_notifyPreAuthStatus (pAdmCtrl, RSN_PRE_AUTH_END); |
| pAdmCtrl->numberOfPreAuthCandidates = 0; |
| return; |
| } |
| |