prima: WLAN Driver Release 3.1.7.9

This is the initial release of the Prima WLAN Driver
diff --git a/CORE/BAP/src/bapRsn8021xAuthFsm.c b/CORE/BAP/src/bapRsn8021xAuthFsm.c
new file mode 100644
index 0000000..9c89829
--- /dev/null
+++ b/CORE/BAP/src/bapRsn8021xAuthFsm.c
@@ -0,0 +1,1614 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Woodside Networks, Inc proprietary. All rights reserved.
+ * $File: //depot/software/projects/feature_branches/gen5_phase1/os/linux/classic/ap/apps/ssm/auth8021x/ani8021xAuthRsnFsm.c $
+ *
+ * Contains definitions for the RSN EAPOL-Key FSM on the
+ * authenticator side. This is based on 802.11i.
+ *
+ * Author:      Mayank D. Upadhyay
+ * Date:        19-December-2002
+ * History:-
+ * Date         Modified by     Modification Information
+ * ------------------------------------------------------
+ *
+ */
+#include "vos_types.h"
+#include "bapRsnSsmServices.h"
+#include "bapRsnSsmEapol.h"
+#include "bapRsnErrors.h"
+#include "bapInternal.h"
+#include "bapRsn8021xFsm.h"
+#include "bapRsn8021xAuthFsm.h"
+#include "vos_utils.h"
+#include "vos_memory.h"
+#include "vos_timer.h"
+#include "bapRsnTxRx.h"
+#include "bapRsnSsmAesKeyWrap.h"
+#include "btampFsm.h"
+
+// The different states that this FSM transitions through
+#define DISCONNECT           0
+#define DISCONNECTED         1
+#define INITIALIZE           2
+#define AUTHENTICATION       3
+#define AUTHENTICATION_2     4
+#define GET_PSK              5   
+#define GET_EAP_KEY          6
+#define PTK_START            7
+#define PTK_INIT_NEGO        8
+#define PTK_INIT_NEGO_TX     9
+#define PTK_INIT_DONE       10
+#define UPDATE_KEYS_REQ     11
+#define INTEG_FAILURE       12
+#define KEY_UPDATE          13
+#define NUM_STATES (KEY_UPDATE + 1)
+
+
+
+static tAuthRsnFsmConsts authConsts = { 2000, 3 };  //timeout, retry limit
+static v_U8_t aniSsmIeRsnOui[] = ANI_SSM_IE_RSN_OUI;
+
+
+/**************************************
+ * Static functions in this module
+ **************************************/
+
+static 
+int zeroOutPtk(tAuthRsnFsm *fsm);
+static 
+int stopAllTimers(tAuthRsnFsm *fsm);
+
+static
+int checkMic(tAuthRsnFsm *fsm, 
+             tAniEapolKeyAvailEventData *data);
+
+static 
+int checkLocalReplayCounter(tAuthRsnFsm *fsm, 
+                            tAniEapolKeyAvailEventData *data);
+static 
+int checkPeerReplayCounter(tAuthRsnFsm *fsm, 
+                           tAniEapolKeyAvailEventData *data);
+
+static int checkInfoElement(tAuthRsnFsm *fsm,
+                            tAniEapolKeyAvailEventData *data);
+
+static
+int derivePtk(tAuthRsnFsm *fsm, 
+              tAniEapolKeyAvailEventData *data);
+
+
+static int checkTransition(tAuthRsnFsm *fsm, void *arg);
+
+static int
+gotoStateInit(tAuthRsnFsm *fsm);
+
+static void msg2TimerCallback( void * );
+static void msg4TimerCallback( void * );
+
+static int authRsnRxFrameHandler( v_PVOID_t pvosGCtx, vos_pkt_t *pPacket );
+static int authRsnTxCompleteHandler( v_PVOID_t pvosGCtx, vos_pkt_t *pPacket, VOS_STATUS retStatus );
+
+/********************************
+ * Functions Forward Declarations
+ ********************************/
+
+int authRsnAuthStartEventHandler( tAuthRsnFsm *fsm );
+int authRsnAuthDisconEventHandler( tAuthRsnFsm *fsm );
+
+/*************************
+ * The exported functions
+ *************************/
+
+/**
+ * authRsnFsmInit
+ *
+ * FUNCTION:
+ * Initializes the constants and the callbacks needed by this FSM
+ * module.
+ *
+ * @param consts the various constant values needed by this FSM
+ * @param cb callbacks to the various procedures needed by this FSM
+ *
+ * @return ANI_OK if the operation succeeds
+ */
+int
+authRsnFsmInit(tAuthRsnFsmConsts *constsIn)
+{
+    // TODO: Read the constants in from config
+    // authConsts = *constsIn;
+    authConsts.timeoutPeriod = 2000;    //ms
+    authConsts.maxTries = 3;
+
+    return ANI_OK;
+}
+
+/**
+ * authRsnFsmCreate
+ *
+ * FUNCTION
+ * Allocates and initializes the state of an RSN key FSM instance for
+ * the given STA context.
+ * 
+ * @parm staCtx the STA context whose instance is being created
+ * @param pskBased pass in eANI_BOOLEAN_TRUE is this STA is to be
+ * authenticated based on a pre-shared key as opposed to EAP.
+ *
+ * @return ANI_OK if the operation succeeds
+ */
+int
+authRsnFsmCreate(tBtampContext *ctx)
+{
+    int retVal = ANI_OK;
+    tAuthRsnFsm *fsm = &ctx->uFsm.authFsm;
+
+    // First, clear everything out
+    vos_mem_zero( fsm, sizeof(tAuthRsnFsm));
+
+    if( !VOS_IS_STATUS_SUCCESS( bapRsnRegisterTxRxCallbacks( authRsnTxCompleteHandler,
+                                            authRsnRxFrameHandler ) ) )
+    {
+        return ANI_ERROR;
+    }
+
+    if( !VOS_IS_STATUS_SUCCESS( bapRsnRegisterRxCallback( ctx->pvosGCtx ) ) )
+    {
+        return ANI_ERROR;
+    }
+
+    // Allocate the station context
+    fsm->staCtx = (tStaContext *)vos_mem_malloc( sizeof(tStaContext) );
+    if (fsm->staCtx == NULL) 
+    {
+        retVal = ANI_E_MALLOC_FAILED;
+        VOS_ASSERT( 0 );
+        goto error;
+    }
+    // Clear out the station context
+    vos_mem_zero( fsm->staCtx, sizeof(tStaContext) );
+    
+    fsm->ctx = ctx;
+    fsm->staCtx->authRsnFsm = fsm;
+    //Only support CCMP
+    fsm->staCtx->pwCipherType = eCSR_ENCRYPT_TYPE_AES;
+
+    if( !VOS_IS_STATUS_SUCCESS( vos_timer_init( &fsm->msg2Timer, VOS_TIMER_TYPE_SW, msg2TimerCallback, fsm ) ) )
+    {
+        retVal = ANI_E_MALLOC_FAILED;
+        VOS_ASSERT( 0 );
+        goto error;
+    }
+
+    if( !VOS_IS_STATUS_SUCCESS( vos_timer_init( &fsm->msg4Timer, VOS_TIMER_TYPE_SW, msg4TimerCallback, fsm ) ) )
+    {
+        retVal = ANI_E_MALLOC_FAILED;
+        VOS_ASSERT( 0 );
+        goto error;
+    }
+
+    retVal = aniAsfPacketAllocateExplicit(&fsm->lastEapol,
+                                          RSN_MAX_PACKET_SIZE,
+                                          EAPOL_TX_HEADER_SIZE );
+    if (retVal != ANI_OK) 
+    {
+        VOS_ASSERT( 0 );
+        goto error;
+    }
+
+    aniAsfPacketAllocate(&fsm->staCtx->pmk);
+    if (fsm->staCtx->pmk == NULL) 
+    {
+        retVal = ANI_E_MALLOC_FAILED;
+        VOS_ASSERT( 0 );
+        goto error;
+    }
+
+    aniAsfPacketAllocateExplicit(&fsm->staCtx->ieSta,
+                                 RSN_IE_MAX_PACKET_SIZE,
+                                 RSN_IE_HEADER_SIZE );
+    if (fsm->staCtx->ieSta == NULL) 
+    {
+        retVal = ANI_E_MALLOC_FAILED;
+        VOS_ASSERT( 0 );
+        goto error;
+    }
+
+    fsm->cryptHandle = 0;
+    if( !VOS_IS_STATUS_SUCCESS( vos_crypto_init( &fsm->cryptHandle ) ) )
+    {
+        retVal = ANI_E_FAILED;
+        VOS_ASSERT( 0 );
+        goto error;
+    }
+
+    fsm->currentState = INITIALIZE;
+    gotoStateInit(fsm);
+
+    //We can call this function here because it is connected at this time
+    authRsnFsmProcessEvent( fsm, RSN_FSM_AUTH_START, NULL );
+
+    return ANI_OK;
+
+ error:
+    authRsnFsmFree(ctx);
+
+    return retVal;
+    
+}
+
+/**
+ * authRsnFsmFree
+ *
+ * FUNCTION
+ * Frees a previously allocated RSN Key FSM in a STA context. If the
+ * RSN Key FSM is not yet allocated, then this is an error.
+ * 
+ * @param ctx the STA context whose FSM instance is to be freed
+ *
+ * @return ANI_OK if the operation succeeds
+ */
+int
+authRsnFsmFree(tBtampContext *ctx)
+{
+    tAuthRsnFsm *fsm = &ctx->uFsm.authFsm;
+
+    VOS_ASSERT(fsm);
+
+    if( fsm->cryptHandle)
+    {
+        vos_crypto_deinit( fsm->cryptHandle );
+    }
+     
+    bapRsnClearTxRxCallbacks(); 
+
+    if ( fsm->staCtx )
+    {
+        fsm->staCtx->authRsnFsm = NULL;
+    }
+
+    if ( VOS_TIMER_STATE_UNUSED != fsm->msg2Timer.state ) vos_timer_destroy( &fsm->msg2Timer );
+    if ( VOS_TIMER_STATE_UNUSED != fsm->msg4Timer.state ) vos_timer_destroy( &fsm->msg4Timer );
+
+    if (fsm->lastEapol)
+    {    
+        aniAsfPacketFree(fsm->lastEapol);
+        fsm->lastEapol = NULL; 
+    }
+
+    if( fsm->staCtx )
+    {
+        if( fsm->staCtx->pmk )
+        {
+            aniAsfPacketFree( fsm->staCtx->pmk );
+            fsm->staCtx->pmk = NULL;
+        }
+       vos_mem_free(fsm->staCtx);
+       fsm->staCtx = NULL; 
+    }
+
+    vos_mem_zero( fsm, sizeof(tAuthRsnFsm) );
+
+    return ANI_OK;
+}
+
+/**
+ * authRsnFsmProcessEvent
+ *
+ * FUNCTION
+ * Passes an event to the RSN key FSM instance for immediate processing.
+ * 
+ * @param fsm the RSN Key FSM instance
+ * @param eventId the AAG event to process
+ * @param arg an optional argument for this event
+ *
+ * @return ANI_OK if the operation succeeds
+ */
+int
+authRsnFsmProcessEvent(tAuthRsnFsm *fsm, tRsnFsmEvent eventId, void *arg)
+{
+    VOS_ASSERT(fsm);
+
+    switch (eventId) {
+    case RSN_FSM_TIMER_EXPIRED:
+        // Proceed straight to checkTransition
+        break;
+    case RSN_FSM_AUTH_START:
+        fsm->authReq = eANI_BOOLEAN_TRUE;
+        authRsnAuthStartEventHandler(fsm);
+        break;
+    case RSN_FSM_EAPOL_FRAME_AVAILABLE:
+        fsm->eapolAvail = eANI_BOOLEAN_TRUE;
+        break;
+    case RSN_FSM_DISCONNECT:
+        fsm->disconnect = eANI_BOOLEAN_TRUE;
+        authRsnAuthDisconEventHandler(fsm);
+        break;
+    case RSN_FSM_INTEG_FAILED:
+        fsm->integFailed = eANI_BOOLEAN_TRUE;
+        break;
+    default:
+        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, 
+            "Unknown event for Auth RSN Key Fsm: %d\n", eventId);
+        VOS_ASSERT( 0 );
+        return ANI_E_ILLEGAL_ARG;
+        break;
+    }
+
+    checkTransition(fsm, arg);
+
+    return ANI_OK;;
+}
+
+
+int
+authRsnAuthStartEventHandler(tAuthRsnFsm *fsm)
+{
+    static v_U8_t btampStaRSNIE[] = {0x30, 0x14, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04, 0x01, 0x00, 
+        0x00, 0x0f, 0xac, 0x04, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x02, 0x00, 0x00 };
+    // Copy required info
+    vos_mem_copy( &fsm->staCtx->authMac, fsm->ctx->self_mac_addr, 6);
+    vos_mem_copy( &fsm->staCtx->suppMac, fsm->ctx->peer_mac_addr, 6);
+    aniAsfPacketAppendBuffer( fsm->staCtx->pmk, fsm->ctx->key_material, fsm->ctx->key_length);
+
+    aniAsfPacketAppendBuffer( fsm->staCtx->ieSta, btampStaRSNIE, sizeof(btampStaRSNIE));
+    return ANI_OK;
+}
+
+int
+authRsnAuthDisconEventHandler(tAuthRsnFsm *fsm)
+{
+    // Free Stactx .?
+    return ANI_OK;
+}
+
+/***********************
+ * The static functions
+ ***********************/
+
+static int
+gotoStateInit(tAuthRsnFsm *fsm)
+{
+    fsm->currentState = INITIALIZE;
+
+    // TODO: Move this to a global position which applies to WEP as
+    // well 
+    //initGlobalKeys = eANI_BOOLEAN_FALSE; 
+
+    fsm->authReq = eANI_BOOLEAN_FALSE;
+    fsm->eapolAvail = eANI_BOOLEAN_FALSE;
+    fsm->disconnect = eANI_BOOLEAN_FALSE;
+    fsm->integFailed = eANI_BOOLEAN_FALSE;
+
+    fsm->numTries = 0;
+
+    // Create two replay counter's..one for our requests, and another
+    // for STA's requests. Initialize the first one randomly.
+    aniSsmReplayCtrCreate(fsm->cryptHandle, &fsm->staCtx->localReplayCtr, 
+                          ANI_EAPOL_KEY_RSN_RSC_SIZE, 0);
+    aniSsmReplayCtrCreate(fsm->cryptHandle, &fsm->staCtx->peerReplayCtr, 
+                          ANI_EAPOL_KEY_RSN_RSC_SIZE, 0);
+
+    return ANI_OK;
+}
+
+static int
+gotoStateAuthentication(tAuthRsnFsm *fsm)
+{
+    fsm->currentState = AUTHENTICATION;
+
+    zeroOutPtk(fsm);
+    fsm->authReq = eANI_BOOLEAN_FALSE;
+
+    checkTransition(fsm, NULL); // UCT rule
+
+    return ANI_OK;
+}
+
+static int
+gotoStateAuthentication2(tAuthRsnFsm *fsm)
+{
+    fsm->currentState = AUTHENTICATION_2;
+
+    if( !VOS_IS_STATUS_SUCCESS( vos_rand_get_bytes( fsm->cryptHandle, fsm->aNonce, ANI_EAPOL_KEY_RSN_NONCE_SIZE ) ) )
+    {
+        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+            "gotoStateAuthentication2 fail to get random number. Disconnect\n" );
+        bapAuthDisconnect( fsm->ctx );
+        return ANI_ERROR;
+    }
+    fsm->numTries = 0;
+
+    checkTransition(fsm, NULL); // UCT rule
+
+    return ANI_OK;
+}
+
+
+static int
+gotoStateGetPsk(tAuthRsnFsm *fsm)
+{
+    //This is simply a transaction because we already have the PMK. We always do.
+    fsm->currentState = GET_PSK;
+
+    fsm->numTries = 0;
+    
+    checkTransition(fsm, NULL);
+    
+    return ANI_OK;
+}
+
+static int
+gotoStatePtkStart(tAuthRsnFsm *fsm)
+{
+    tAniEapolRsnKeyDesc txDesc;
+    int retVal;
+
+    fsm->msg2TimeOut = VOS_FALSE;
+    fsm->currentState = PTK_START;
+
+    // Create a new packet if we don't have one to retransmit
+    //if (aniAsfPacketGetLen(fsm->lastEapol) == 0) 
+#if 0    
+    if( fsm->lastEapol )
+    {
+        aniAsfPacketFree( fsm->lastEapol );
+        fsm->lastEapol = NULL;
+
+    retVal = aniAsfPacketAllocateExplicit(&fsm->lastEapol,
+                                          RSN_MAX_PACKET_SIZE,
+                                          EAPOL_TX_HEADER_SIZE );
+#endif    
+    aniAsfPacketEmptyExplicit(fsm->lastEapol, 
+                              EAPOL_TX_HEADER_SIZE);
+    //}
+   // if (1) 
+    //{
+
+        vos_mem_zero( &txDesc, sizeof(txDesc) );
+
+        // The Key Information bits...
+        if (fsm->staCtx->pwCipherType == eCSR_ENCRYPT_TYPE_AES) 
+        {
+            txDesc.info.keyDescVers = ANI_EAPOL_KEY_DESC_VERS_AES;
+        } 
+        else {
+            return ANI_E_ILLEGAL_ARG;
+        }
+        txDesc.info.unicastFlag = eANI_BOOLEAN_TRUE;
+        txDesc.info.ackFlag = eANI_BOOLEAN_TRUE;
+
+        // The other fields...
+        txDesc.keyLen = aagGetKeyMaterialLen(fsm->staCtx->pwCipherType);
+        aniSsmReplayCtrNext(fsm->staCtx->localReplayCtr, txDesc.replayCounter);
+        vos_mem_copy(txDesc.keyNonce, fsm->aNonce, sizeof(txDesc.keyNonce));
+
+        retVal = aniEapolWriteKey(fsm->cryptHandle,
+                                  fsm->lastEapol,
+                                  fsm->staCtx->suppMac,
+                                  fsm->staCtx->authMac,
+                                  ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW,
+                                  &txDesc,
+                                  NULL, 0);
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) )
+        {
+            return retVal;
+        }
+#if 0
+    } 
+    else {
+        retransmit = eANI_BOOLEAN_TRUE;
+    }
+#endif    
+
+    if( VOS_IS_STATUS_SUCCESS( bapRsnSendEapolFrame( fsm->ctx->pvosGCtx, fsm->lastEapol ) ) )
+    {
+        retVal = ANI_OK;
+    }
+    else
+    {
+        //we fail to send the eapol frame disconnect
+        bapAuthDisconnect( fsm->ctx );
+        retVal = ANI_ERROR;
+    }
+
+    return retVal;
+}
+
+static int
+gotoStatePtkInitNego(tAuthRsnFsm *fsm, void *arg)
+{
+    fsm->currentState = PTK_INIT_NEGO;
+
+    // Replay counter will be automatically updated when we create a
+    // new packet
+
+    fsm->numTries = 0;
+    aniAsfPacketEmptyExplicit(fsm->lastEapol, 
+                              EAPOL_TX_HEADER_SIZE);
+
+    checkTransition(fsm, arg);
+
+    return ANI_OK;
+}
+
+// Use this only with trusted IE like the one we generated locally
+static int
+getRsnIeFromAdvertizedIes(tAuthRsnFsm *fsm, v_U8_t **rsnIe)
+{
+    int retVal = ANI_E_ILLEGAL_ARG;
+    v_U8_t *ptr = fsm->advertizedRsnIe;
+
+    if (*ptr == ANI_SSM_IE_RSN_ELEM_ID) 
+    {
+        retVal = *(ptr + 1) + 2; // The L field from the TLV + 2B TL
+        *rsnIe = ptr;
+    }
+
+    return retVal;
+}
+
+// Use this only with trusted IE like the one we generated locally
+static void
+addPad( 
+    v_U8_t *dataBytes,
+    int dataLen,
+    int padLen)
+{
+    int i;
+
+    // The first byte of padding is 0xdd.  The rest are 0x00's
+    // See 802.11i section 8.5.2 subsection "Key Data Encapsulation"
+
+    for ( i=dataLen ; i < dataLen+padLen; i++) 
+    {
+        if ( i == dataLen ) 
+        {
+            dataBytes[i] = 0xdd;
+        } 
+        else {
+            dataBytes[i] = 0x00;
+        }
+    }
+
+    return;
+}
+
+/**
+ * aagAppendGroupKeyForRsn
+ *
+ * Appends the group key to the packet in the RSN key encapulation format.
+ *
+ * @param packet - the packet to append to
+ * @param radioId - the radio whose group key needs to be appended
+ *
+ * @return ANI_OK if the operation succeeds
+ */
+#define STATIC_WEP_KEY_LEN 16
+#define GROUP_KEY_ID 0
+#define ANI_SSM_IE_RSN_KEY_DATA_ENCAPS_ID       0xDD
+#define ANI_SSM_IE_RSN_GROUP_KEY_DATA_ENCAPS_ID 1
+
+int
+aagAppendGroupKeyForRsn(tAniPacket *packet)
+{
+#if 0
+    tAniPacket *groupKey = NULL;
+#else
+    tANI_U8 groupKey[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                          0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15};
+#endif
+    tANI_U8 *groupKeyBytes = NULL;
+    tANI_U8 *lenPtr = NULL;
+    tANI_U8 *endPtr = NULL;
+    int groupKeyLen;
+    int retVal;
+
+#if 0
+    groupKey = AAG_GROUP_KEY(radioId);
+    if (groupKey == NULL) {
+        ANI_AAG_LOG_E("Group key is not yet set on radio %d, id %d!",
+                      radioId, AAG_GROUP_KEY_ID(radioId));
+        assert(0 && "Group key is still NULL!");
+        return ANI_E_FAILED;
+    }
+
+    groupKeyLen = aniAsfPacketGetBytes(groupKey, &groupKeyBytes);
+    CHECK_NO_ERROR(groupKeyLen);
+
+    if (aagConfig.logLevel >= LOG_INFO) {
+        ANI_AAG_LOG_D("Will encapsulate group key bytes %s",
+                      aniAsfHexStr(groupKeyBytes, groupKeyLen));
+    }
+#else
+    groupKeyBytes = groupKey;
+
+    groupKeyLen = STATIC_WEP_KEY_LEN;
+#endif
+
+    /*
+     * Add the key data encapsulation needed for RSN/WPA2
+     */
+
+    // The IE ID
+    retVal = aniAsfPacketAppend8(packet, ANI_SSM_IE_RSN_KEY_DATA_ENCAPS_ID);
+    //CHECK_NO_ERROR(retVal);
+
+    // Obtain the position for the length
+    aniAsfPacketGetBytesFromTail(packet, &lenPtr);
+
+    // Write out a dummy length - we'll fill this in later. It will be 
+    // 6 bytes more than the length of the GTK
+    retVal = aniAsfPacketAppend8(packet, 0);
+    //CHECK_NO_ERROR(retVal);
+
+    // Copy the RSN OUI
+    retVal = aniAsfPacketAppendBuffer(packet, aniSsmIeRsnOui, sizeof(aniSsmIeRsnOui));
+    //CHECK_NO_ERROR(retVal);
+
+    // Indicate that the key type is group key
+    retVal = aniAsfPacketAppend8(packet, ANI_SSM_IE_RSN_GROUP_KEY_DATA_ENCAPS_ID);
+    //CHECK_NO_ERROR(retVal);
+ 
+    // Copy the key-id to the first two bits of the next byte
+    // Copy the Tx bit the third bit of the same byte
+    // (Here, I assume the Group Key is to be used for both STA Tx and Rx)
+    retVal = aniAsfPacketAppend8(
+            packet,
+            GROUP_KEY_ID );
+            //AAG_GROUP_KEY_ID(radioId) );
+    //CHECK_NO_ERROR(retVal);
+
+    retVal = aniAsfPacketMoveRight(packet, 1); // Reserved bits (1 byte)
+    //CHECK_NO_ERROR(retVal);
+
+    // Copy the real key bytes
+    retVal = aniAsfPacketAppendBuffer(packet, groupKeyBytes, groupKeyLen);
+    //CHECK_NO_ERROR(retVal);
+    
+    // Calculate and enter the length of the entire encoding
+    aniAsfPacketGetBytesFromTail(packet, &endPtr);
+    *lenPtr = endPtr - (lenPtr + 1) ; // subtract one to avoid tail
+
+    return retVal;
+}
+
+static int
+gotoStatePtkInitNegoTx(tAuthRsnFsm *fsm)
+{
+    tAniEapolRsnKeyDesc txDesc;
+    v_BOOL_t retransmit = eANI_BOOLEAN_FALSE;
+    v_U8_t *rsnWpaIe = NULL;
+    int rsnWpaIeLen;
+    static tAniPacket *keyData = NULL;
+    // The longest length...the extra 8 bytes account for RSN key data
+    // encapsulation
+    v_U8_t paddedGroupKeyEncaps[1024];
+    int padLen = 0;
+    v_U8_t *groupKeyBytes;
+    int groupKeyLen;
+    v_U8_t *wrappedKey = NULL;
+    // Variables used for RC4 GTK wrap
+    //v_U8_t keyIv[ANI_EAPOL_KEY_RSN_IV_SIZE];
+    //v_U32_t keyIvLsb;
+    int retVal = 0;
+
+    //invalidate this
+    fsm->msg4TimeOut = VOS_FALSE;
+    fsm->currentState = PTK_INIT_NEGO_TX ;
+
+    if (keyData == NULL) 
+    {
+        // Allocate the packet the first time around that you enter
+        retVal = aniAsfPacketAllocateExplicit(&keyData, 1024, 10);
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) )
+        {
+            return retVal;
+        }
+    } 
+    else {
+        // Just empty out the packet
+        aniAsfPacketEmptyExplicit(keyData, 10);
+    }
+
+    do
+    {
+        // Create a new EAPOL frame if we don't have one to retransmit
+        //if (aniAsfPacketGetLen(fsm->lastEapol) == 0) 
+#if 0
+        if( fsm->lastEapol )
+         {
+             aniAsfPacketFree( fsm->lastEapol );
+             fsm->lastEapol = NULL;
+
+             retVal = aniAsfPacketAllocateExplicit(&fsm->lastEapol,
+                                          RSN_MAX_PACKET_SIZE,
+                                          EAPOL_TX_HEADER_SIZE );
+#endif     
+             aniAsfPacketEmptyExplicit(fsm->lastEapol, 
+                              EAPOL_TX_HEADER_SIZE);
+      //  }
+
+        if (1) 
+        {
+
+            vos_mem_zero( &txDesc, sizeof(txDesc) );
+
+            // The Key Information bits...
+            if (fsm->staCtx->pwCipherType == eCSR_ENCRYPT_TYPE_AES) 
+            {
+                txDesc.info.keyDescVers = ANI_EAPOL_KEY_DESC_VERS_AES;
+            } 
+            else {
+                txDesc.info.keyDescVers = ANI_EAPOL_KEY_DESC_VERS_RC4;
+            }
+            txDesc.info.unicastFlag = eANI_BOOLEAN_TRUE;
+            txDesc.info.installFlag = eANI_BOOLEAN_TRUE;
+            txDesc.info.ackFlag = eANI_BOOLEAN_TRUE;
+            txDesc.info.micFlag = eANI_BOOLEAN_TRUE;
+
+            txDesc.keyLen = aagGetKeyMaterialLen(fsm->staCtx->pwCipherType);
+            aniSsmReplayCtrNext(fsm->staCtx->localReplayCtr, txDesc.replayCounter);
+            vos_mem_copy(txDesc.keyNonce, fsm->aNonce, sizeof(txDesc.keyNonce));
+
+            // Add the RSN IE (but not any WPA IE)
+            rsnWpaIeLen = getRsnIeFromAdvertizedIes(fsm, &rsnWpaIe);
+
+            if( !ANI_IS_STATUS_SUCCESS( rsnWpaIeLen) ) break;
+
+            retVal = aniAsfPacketAppendBuffer(keyData, rsnWpaIe, rsnWpaIeLen);
+            if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+
+            // Add the RSN group key encapsulation
+            retVal = aagAppendGroupKeyForRsn ( keyData );
+
+            if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+
+            groupKeyLen = aniAsfPacketGetBytes(keyData, &groupKeyBytes);
+            if( !ANI_IS_STATUS_SUCCESS( groupKeyLen ) ) 
+            {
+                retVal = ANI_E_FAILED;
+                break;
+            }
+
+            txDesc.info.secureFlag = eANI_BOOLEAN_TRUE;
+            txDesc.info.encKeyDataFlag = eANI_BOOLEAN_TRUE;
+
+            if ( fsm->staCtx->pwCipherType == eCSR_ENCRYPT_TYPE_AES ) 
+            {
+                /*
+                 * Use the AES key wrap algorithm if either one of the pairwise
+                 * key or the group key is an AES key.
+                 *
+                 * If the key being sent is not a multiple of
+                 * ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE, then pad it with
+                 * zeroes. e.g., if we are sending a WEP key of 5 or 13
+                 * bytes.
+                 */
+                VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                           "AES Key Wrap invoked. groupKeyLen = %d", groupKeyLen);
+
+                padLen = groupKeyLen % ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE;
+                if (padLen != 0) {
+                    padLen = ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE - padLen;
+            
+                    VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                               "Before AES Key Wrap: padLen = %d", padLen);
+
+                    if (groupKeyLen + padLen > sizeof(paddedGroupKeyEncaps)) {
+#if 0
+                        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                                   "Cannot encode group key encapsulation of len %d and cipher type %s "
+                                   "to send to %s %s (aid %d, radio %d, user %s)",
+                                   groupKeyLen,
+                                   aniSsmIntGetCipherStr(AAG_GROUP_CIPHER(fsm->ctx->radioId)),
+                                   (fsm->ctx->bpIndicator ? "BP" : "STA"),
+                                   aniAsfHexStr(fsm->ctx->suppMac, sizeof(tAniMacAddr)),
+                                   fsm->ctx->aid,
+                                   fsm->ctx->radioId,
+                                   aagGetStaUserId(fsm->ctx));
+#endif
+                         retVal = ANI_E_FAILED;
+                    }
+                    // OK, after you compute the pad length, you need to 
+                    // add the padding  - 0xdd followed by 0x00's
+                    addPad( groupKeyBytes , groupKeyLen , padLen );
+                    // add the padding length
+                    groupKeyLen += padLen;
+                    // IMMEDIATELY adjust the packet size to reflect the pad 
+                    aniAsfPacketMoveRight(keyData, padLen); 
+                    if( !ANI_IS_STATUS_SUCCESS( retVal) ) break;
+                }
+            
+                VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                           "Before AES Key Wrap: padded groupKeyLen = %d", groupKeyLen);
+
+                retVal = aniSsmAesKeyWrap(fsm->cryptHandle, groupKeyBytes, groupKeyLen,
+                                          fsm->staCtx->ptk + ANI_EAPOL_KEY_RSN_MIC_SIZE,
+                                          ANI_EAPOL_KEY_RSN_ENC_KEY_SIZE,
+                                          &wrappedKey);
+                if( !ANI_IS_STATUS_SUCCESS( retVal) ) break;
+                // This doesn't work...
+                //groupKeyBytes = wrappedKey;
+                //groupKeyLen += ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE;
+                // ...here is the right way to do it
+                // Add the length of the prepended IV A[0]
+                if (NULL == wrappedKey)
+                {
+                    break;
+                }
+                groupKeyLen += ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE;
+                memcpy( groupKeyBytes, wrappedKey, groupKeyLen);
+                // Free the array used to hold the wrapped key
+                if (wrappedKey) vos_mem_free( wrappedKey);
+                // IMMEDIATELY adjust the packet size to reflect the IV 
+                aniAsfPacketMoveRight(keyData, ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE);
+            } 
+            else {
+            
+                VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                    "Auth RC4 Key Wrap invoked. groupKeyLen = %d", groupKeyLen);
+            }
+            txDesc.keyDataLen = aniAsfPacketGetBytes(keyData, &txDesc.keyData);
+
+            retVal = aniEapolWriteKey(fsm->cryptHandle,
+                                      fsm->lastEapol,
+                                      fsm->staCtx->suppMac,
+                                      fsm->staCtx->authMac,
+                                      ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW,
+                                      &txDesc,
+                                      fsm->staCtx->ptk,
+                                      CSR_AES_KEY_LEN);
+            if( !ANI_IS_STATUS_SUCCESS( retVal) ) break;
+        } 
+        else {
+            retransmit = eANI_BOOLEAN_TRUE;
+        }
+
+        if( VOS_IS_STATUS_SUCCESS( bapRsnSendEapolFrame( fsm->ctx->pvosGCtx, fsm->lastEapol ) ) )
+        {
+            retVal = ANI_OK;
+        }
+        else
+        {
+            //we fail to send the eapol frame disconnect
+            bapAuthDisconnect( fsm->ctx );
+            retVal = ANI_ERROR;
+        }
+
+    }while( 0 );
+
+    return retVal;
+}
+
+static int
+gotoStatePtkInitDone(tAuthRsnFsm *fsm, tAniEapolKeyAvailEventData *data)
+{
+    int retVal;
+    tAniEapolRsnKeyDesc *rxDesc;
+    tCsrRoamSetKey setKeyInfo;
+
+    fsm->currentState = PTK_INIT_DONE;
+
+    rxDesc = data->keyDesc;
+
+    vos_mem_zero( &setKeyInfo, sizeof( tCsrRoamSetKey ) );
+    setKeyInfo.encType = eCSR_ENCRYPT_TYPE_AES;
+    setKeyInfo.keyDirection = eSIR_TX_RX;
+    vos_mem_copy( setKeyInfo.peerMac, fsm->staCtx->suppMac, sizeof( tAniMacAddr ) );
+    setKeyInfo.paeRole = 0; //this is a supplicant
+    setKeyInfo.keyId = 0;   //always
+    setKeyInfo.keyLength = CSR_AES_KEY_LEN; 
+    vos_mem_copy( setKeyInfo.Key, (v_U8_t *)fsm->staCtx->ptk + (2 * CSR_AES_KEY_LEN ), CSR_AES_KEY_LEN );
+    //fsm->suppCtx->ptk contains the 3 16-bytes keys. We need the last one.
+    if( VOS_IS_STATUS_SUCCESS( bapSetKey( fsm->ctx->pvosGCtx, &setKeyInfo ) ) )
+    {
+        //Done
+        aniAsfPacketEmptyExplicit(fsm->lastEapol, EAPOL_TX_HEADER_SIZE);
+        retVal = ANI_OK;
+    }
+    else
+    {
+        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "Auth: gotoStatePtkInitDone fail to set key\n" );
+        retVal = ANI_ERROR;
+    }
+
+    return retVal;
+}
+
+static int
+gotoStateUpdateKeysReq(tAuthRsnFsm *fsm, tAniEapolKeyAvailEventData *data)
+{
+    tAniEapolRsnKeyDesc *rxDesc;
+
+    fsm->currentState = UPDATE_KEYS_REQ;
+
+    rxDesc = data->keyDesc;
+
+    aniSsmReplayCtrUpdate(fsm->staCtx->peerReplayCtr, rxDesc->replayCounter);
+
+    checkTransition(fsm, data);
+
+    return ANI_OK;
+}
+
+static int
+gotoStateIntegFailure(tAuthRsnFsm *fsm, tSirMicFailureInfo *micFailureInfo)
+{
+    fsm->currentState = INTEG_FAILURE;
+
+    fsm->integFailed = eANI_BOOLEAN_FALSE;
+
+    checkTransition(fsm, NULL); // UCT
+
+    return ANI_OK;
+}
+
+static int
+gotoStateKeyUpdate(tAuthRsnFsm *fsm)
+{
+    fsm->currentState = KEY_UPDATE;
+
+    if( VOS_IS_STATUS_SUCCESS( vos_rand_get_bytes(fsm->cryptHandle, fsm->aNonce, ANI_EAPOL_KEY_RSN_NONCE_SIZE) ) )
+    {
+
+        // Replay counter will be automatically updated when we create a
+        // new packet
+        
+        checkTransition(fsm, NULL); // UCT
+
+        return ANI_OK;
+    }
+    return ANI_ERROR;
+}
+
+static int
+gotoStateDisconnect(tAuthRsnFsm *fsm)
+{
+    fsm->currentState = DISCONNECT;
+
+    //What else do we need to clean up? Or BAP will call our vleanup function?
+
+    // FSM does not exist after this...
+    bapAuthDisconnect( fsm->ctx );
+
+    return ANI_OK;
+}
+
+static 
+int zeroOutPtk(tAuthRsnFsm *fsm)
+{
+    return ANI_OK;
+}
+
+static 
+int stopAllTimers(tAuthRsnFsm *fsm)
+{
+    vos_timer_stop( &fsm->msg2Timer );
+    vos_timer_stop( &fsm->msg4Timer );
+
+    return ANI_OK;
+}
+
+static
+int derivePtk(tAuthRsnFsm *fsm, tAniEapolKeyAvailEventData *data)
+{
+    v_U32_t prfLen;
+    tAniEapolRsnKeyDesc *rxDesc;
+
+    VOS_ASSERT(fsm->staCtx->pmk);
+
+    switch (fsm->staCtx->pwCipherType) 
+    {
+    case eCSR_ENCRYPT_TYPE_AES:
+        prfLen = AAG_RSN_PTK_PRF_LEN_CCMP;
+        break;
+    default:
+        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+            "Auth cannot generate PTK for invalid algorithm %d\n",
+                      fsm->staCtx->pwCipherType);
+        return ANI_E_ILLEGAL_ARG;
+        break;
+    };
+
+    rxDesc = (tAniEapolRsnKeyDesc *) data->keyDesc;
+    return aagPtkPrf(fsm->cryptHandle,
+                     fsm->staCtx->ptk,
+                     prfLen,
+                     fsm->staCtx->pmk,
+                     fsm->staCtx->authMac,
+                     fsm->staCtx->suppMac,
+                     fsm->aNonce,
+                     rxDesc->keyNonce);
+}
+
+static int 
+checkMic(tAuthRsnFsm *fsm, 
+         tAniEapolKeyAvailEventData *data)
+{
+    int retVal;
+
+    retVal = aniEapolKeyCheckMic(fsm->cryptHandle,
+                                 data->eapolFrame,
+                                 ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW,
+                                 data->keyDesc,
+                                 fsm->staCtx->ptk,
+                                 CSR_AES_KEY_LEN);
+
+    if (retVal == ANI_E_MIC_FAILED) 
+    {
+
+        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                     "Auth failed EAPOL-MIC check in pairwise key exchange!\n"); 
+    }
+
+    return retVal;
+}
+
+static int 
+checkLocalReplayCounter(tAuthRsnFsm *fsm, 
+                        tAniEapolKeyAvailEventData *data)
+{
+    int retVal = ANI_E_NULL_VALUE;
+    int cmp;
+    tAniEapolRsnKeyDesc *rxDesc;
+    
+    rxDesc = data->keyDesc;
+    if( rxDesc )
+    {
+        cmp = aniSsmReplayCtrCmp(fsm->staCtx->localReplayCtr, rxDesc->replayCounter);
+
+        // The STA should have sent back the same replay ctr as in our request
+        if (cmp != 0) 
+        {
+            retVal = ANI_E_REPLAY_CHECK_FAILED;
+        }
+        else
+        {
+            retVal = ANI_OK;
+        }
+    }
+
+    return retVal;
+}
+
+static 
+int checkPeerReplayCounter(tAuthRsnFsm *fsm, 
+                           tAniEapolKeyAvailEventData *data)
+{
+    int retVal = ANI_E_NULL_VALUE;
+    int cmp;
+    tAniEapolRsnKeyDesc *rxDesc;
+    
+    rxDesc = data->keyDesc;
+    if( rxDesc )
+    {
+        cmp = aniSsmReplayCtrCmp(fsm->staCtx->peerReplayCtr, rxDesc->replayCounter);
+
+        // The STA should have sent a newer replay ctr than its old
+        // request. The first message is exempted from the check.
+        if (fsm->staCtx->pastFirstPeerRequest && cmp >= 0) 
+        {
+            retVal = ANI_E_REPLAY_CHECK_FAILED;
+        }
+
+        fsm->staCtx->pastFirstPeerRequest = eANI_BOOLEAN_TRUE;
+    }
+
+    return retVal;
+}
+
+static int checkInfoElement(tAuthRsnFsm *fsm,
+                            tAniEapolKeyAvailEventData *data)
+{
+    tAniEapolRsnKeyDesc *desc;
+    v_U8_t *ieStaBytes;
+    int ieStaLen;
+
+    desc = (tAniEapolRsnKeyDesc *) data->keyDesc;
+    if( desc )
+    {
+        ieStaLen = aniAsfPacketGetBytes(fsm->staCtx->ieSta, &ieStaBytes);
+        if( !ANI_IS_STATUS_SUCCESS( ieStaLen ) )
+        {
+            return ieStaLen;
+        }
+
+        if ((desc->keyDataLen != ieStaLen) ||
+            ( !vos_mem_compare(desc->keyData, ieStaBytes, ieStaLen-2) )) 
+        {
+            VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                         "Auth STA sent inconsistent RSN IE!\n");
+            return ANI_E_FAILED;
+        }
+        // Copy RSN IE
+        //vos_mem_copy(fsm->advertizedRsnIe, desc->keyData, ieStaLen);
+        vos_mem_copy(fsm->advertizedRsnIe, ieStaBytes, ieStaLen);
+
+        return ANI_OK;
+    }
+    else
+    {
+        return ANI_E_NULL_VALUE;
+    }
+
+}
+
+static 
+int checkTransition(tAuthRsnFsm *fsm, void *arg)
+{
+    int retVal;
+    tAniEapolKeyAvailEventData *data;
+    tAniEapolRsnKeyDesc *rxDesc;
+    tSirMicFailureInfo *micFailureInfo;
+
+    if (fsm->disconnect) 
+    {
+        stopAllTimers(fsm);
+        gotoStateDisconnect(fsm);
+        return ANI_OK;
+    }
+
+    if (fsm->authReq) 
+    {
+        stopAllTimers(fsm);
+        gotoStateAuthentication(fsm);
+        return ANI_OK;
+    }
+
+    switch (fsm->currentState) 
+    {
+    case INITIALIZE:
+        break;
+    case AUTHENTICATION:
+        gotoStateAuthentication2(fsm);
+        break;
+    case AUTHENTICATION_2:
+        gotoStateGetPsk( fsm );
+        break;
+    case GET_PSK:
+        //We always have PMK otherwise BAP won't let us here
+        gotoStatePtkStart(fsm);
+        break;
+    case PTK_START:
+        if ( fsm->eapolAvail ) 
+        {
+            fsm->eapolAvail = eANI_BOOLEAN_FALSE;
+            if (NULL == arg)
+            {
+                VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                           "arg is NULL, exiting checkTransition()");
+                return ANI_E_FAILED;
+            }
+            data = (tAniEapolKeyAvailEventData *) arg;
+            retVal = checkLocalReplayCounter(fsm, data);
+            if (retVal != ANI_OK)
+                return ANI_OK; // Caller should not fail
+            retVal = derivePtk(fsm, data);
+            if( !ANI_IS_STATUS_SUCCESS( retVal ) )
+            {
+                VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                         "Auth derivePtk failed with code %d!\n", retVal);
+                return retVal;
+            }
+            retVal = checkMic(fsm, data);
+            if (retVal != ANI_OK) 
+            {
+                bapAuthDisconnect( fsm->ctx );
+                return retVal;
+            }
+            retVal = gotoStatePtkInitNego(fsm, arg);
+        } 
+        else if ( fsm->msg2TimeOut ) 
+        {
+            if (fsm->numTries <= authConsts.maxTries) 
+            {
+                VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                             "Auth Retransmitting EAPOL-Key Msg1\n");
+                // Stay in the same state but repeat actions
+                gotoStatePtkStart(fsm);
+            } 
+            else {
+                VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                             "Auth failed to recv EAPOL-Key Msg2 "
+                             "Disconnecting...\n");
+
+                gotoStateDisconnect(fsm);
+            }
+        }
+        break;
+    case PTK_INIT_NEGO:
+        if (NULL == arg)
+        {
+            VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                       "arg is NULL, exiting checkTransition()");
+            return ANI_E_FAILED;
+        }
+        data = (tAniEapolKeyAvailEventData *) arg;
+        retVal = checkInfoElement(fsm, data);
+        if (retVal != ANI_OK) 
+        {
+            gotoStateDisconnect(fsm);
+        } 
+        else {
+            gotoStatePtkInitNegoTx(fsm);
+        }
+        break;
+    case PTK_INIT_NEGO_TX:
+        if (fsm->eapolAvail) 
+        {
+            fsm->eapolAvail = eANI_BOOLEAN_FALSE;
+            if (NULL == arg)
+            {
+                VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                           "arg is NULL, exiting checkTransition()");
+                return ANI_E_FAILED;
+            }
+            data = (tAniEapolKeyAvailEventData *) arg;
+            retVal = checkLocalReplayCounter(fsm, data);
+            if (retVal != ANI_OK)
+                return ANI_OK; // Caller should not fail
+            retVal = checkMic(fsm, data);
+            if (retVal != ANI_OK) 
+            {
+                bapAuthDisconnect( fsm->ctx );
+                return retVal;
+            }
+            retVal = gotoStatePtkInitDone(fsm, data);
+        } else if ( fsm->msg4TimeOut ) 
+        {
+            if (fsm->numTries <= authConsts.maxTries) 
+            {
+                VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                             "Auth retransmitting EAPOL-Key Msg3 \n");
+                // Stay in the same state but repeat actions
+                gotoStatePtkInitNegoTx(fsm);
+            } 
+            else {
+                VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                             "Auth failed to recv EAPOL-Key Msg4 "
+                             "Disconnecting...\n" );
+
+                gotoStateDisconnect(fsm);
+            }
+        }
+        break;
+    case PTK_INIT_DONE:
+        if (fsm->eapolAvail) {
+
+            fsm->eapolAvail = eANI_BOOLEAN_FALSE;
+            if (NULL == arg)
+            {
+                VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                           "arg is NULL, exiting checkTransition()");
+                return ANI_E_FAILED;
+            }
+            data = (tAniEapolKeyAvailEventData *) arg;
+            rxDesc = (tAniEapolRsnKeyDesc *) data->keyDesc;
+
+            if (rxDesc->info.requestFlag) 
+            {
+
+                retVal = checkPeerReplayCounter(fsm, data);
+                if (retVal != ANI_OK)
+                    return ANI_OK; // Caller should not fail
+
+                retVal = checkMic(fsm, data);
+                if (retVal != ANI_OK) 
+                {
+                    bapAuthDisconnect( fsm->ctx->pvosGCtx );
+                    return retVal;
+                }
+
+                retVal = gotoStateUpdateKeysReq(fsm, arg);
+            }
+        } 
+        else if (fsm->integFailed) {
+
+            micFailureInfo = (tSirMicFailureInfo *) arg;
+            gotoStateIntegFailure(fsm, arg);
+
+        }
+        break;
+    case UPDATE_KEYS_REQ:
+
+        if (NULL == arg)
+        {
+            VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                       "arg is NULL, exiting checkTransition()");
+            return ANI_E_FAILED;
+        }
+        data = (tAniEapolKeyAvailEventData *) arg;
+        rxDesc = (tAniEapolRsnKeyDesc *) data->keyDesc;
+
+        if (rxDesc->info.errorFlag) 
+        {
+
+            /*
+             * This was generated by a unicast packet sent from the AP to the STA/BP.
+             * The TX address is the AP's address. The src address is lost.
+             * If the STA is a BP, then the true dst is lost. We will treat
+             * the dst field as the address of the reporter of the MIC failure.
+             */
+
+            micFailureInfo = (tSirMicFailureInfo *) vos_mem_malloc( sizeof(tSirMicFailureInfo) );
+            if( NULL == micFailureInfo )
+            {
+                VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                    "Fail to allocate memory for AuthRsnFsm: %d\n",
+                      fsm->currentState);
+                return ANI_E_MALLOC_FAILED;
+            }
+
+            vos_mem_copy(micFailureInfo->taMacAddr, fsm->staCtx->authMac, sizeof(tAniMacAddr));
+            vos_mem_copy(micFailureInfo->dstMacAddr, fsm->staCtx->suppMac, sizeof(tAniMacAddr));
+            micFailureInfo->multicast = eANI_BOOLEAN_FALSE;
+            // Copy whatever sequence number came in the EAPOL-key message
+            vos_mem_copy(micFailureInfo->TSC, rxDesc->keyRecvSeqCounter, SIR_CIPHER_SEQ_CTR_SIZE);
+            gotoStateIntegFailure(fsm, micFailureInfo);
+            vos_mem_free(micFailureInfo);
+        } 
+        else {
+            // TBD: Untested. Why are local aNonce and local replyCtr not incremented in spec?
+            gotoStatePtkStart(fsm);
+        }
+        break;
+    case INTEG_FAILURE:
+        gotoStateKeyUpdate(fsm);
+        break;
+    case KEY_UPDATE:
+        gotoStatePtkStart(fsm);
+        break;
+    default:
+        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+            "Nothing to do in this state for AuthRsnFsm: %d\n",
+                      fsm->currentState);
+        // Catch all for states that need no change:
+        //        assert(eANI_BOOLEAN_FALSE && "Illegal AuthRsnFsm state!");
+        return ANI_E_FAILED;
+    }
+
+    return ANI_OK;
+}
+
+
+static void msg2TimerCallback( void *pv )
+{
+    tAuthRsnFsm *fsm = (tAuthRsnFsm *)pv;
+    if (NULL == fsm) 
+    {
+        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                     "fsm is NULL in %s", __FUNCTION__);
+
+        return;
+    }
+
+    //Only when waiting for msg2
+    if( PTK_START == fsm->currentState )
+    {
+        fsm->msg2TimeOut = eANI_BOOLEAN_TRUE;
+    }
+    //We may need to synchronize this call
+    authRsnFsmProcessEvent( fsm, RSN_FSM_TIMER_EXPIRED, NULL );
+}
+
+static void msg4TimerCallback( void *pv )
+{
+    tAuthRsnFsm *fsm = (tAuthRsnFsm *)pv;
+    if (NULL == fsm) 
+    {
+        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                     "fsm is NULL in %s", __FUNCTION__);
+
+        return;
+    }
+
+    //Only when we are waiting for msg4
+    if( PTK_INIT_NEGO_TX == fsm->currentState )
+    {
+        fsm->msg4TimeOut = eANI_BOOLEAN_TRUE;
+    }
+    //We may need to synchronize this call
+    authRsnFsmProcessEvent( fsm, RSN_FSM_TIMER_EXPIRED, NULL );
+}
+
+
+//
+//This function alwasy assume the incoming vos_packet is 802_3 frame.
+static int authRsnRxFrameHandler( v_PVOID_t pvosGCtx, vos_pkt_t *pPacket )
+{
+    int retVal = ANI_ERROR;
+    tAniPacket *pAniPacket;
+    tBtampContext *ctx;
+    tAuthRsnFsm *fsm;
+
+    /* Validate params */ 
+    if ((pvosGCtx == NULL) || (NULL == pPacket))
+    {
+        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                     "param is NULL in %s", __FUNCTION__);
+
+        return retVal;
+    }
+
+    ctx = (tBtampContext *)VOS_GET_BAP_CB( pvosGCtx );
+    if (NULL == ctx) 
+    {
+        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                     "ctx is NULL in %s", __FUNCTION__);
+
+        return retVal;
+    }
+
+    fsm = &ctx->uFsm.authFsm;
+    if (NULL == fsm) 
+    {
+        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                     "fsm is NULL in %s", __FUNCTION__);
+
+        return retVal;
+    }
+
+    do
+    {
+        //ToDO: We need to synchronize this. For now, use the simplest form, drop the packet comes later.
+        if( fsm->fReceiving )
+        {
+            VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                " ******authRsnRxFrameHandler receive eapol packet while processing. Drop the new comer\n" );
+            break;
+        }
+        fsm->fReceiving = VOS_TRUE;
+        retVal = bapRsnFormPktFromVosPkt( &pAniPacket, pPacket );
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+        //Now we can process the eapol frame
+        //handler will free the pAniPacket
+        bapRsnEapolHandler( fsm, pAniPacket, VOS_TRUE );
+    }while( 0 );
+
+    fsm->fReceiving = VOS_FALSE;
+    vos_pkt_return_packet( pPacket );
+
+    return retVal;
+}
+
+
+static int authRsnTxCompleteHandler( v_PVOID_t pvosGCtx, vos_pkt_t *pPacket, VOS_STATUS retStatus )
+{
+    tBtampContext *ctx = (tBtampContext *)VOS_GET_BAP_CB( pvosGCtx );
+    tAuthRsnFsm *fsm;
+
+    vos_pkt_return_packet( pPacket );
+    if (NULL == ctx) 
+    {
+        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                     "ctx is NULL in %s", __FUNCTION__);
+
+        return ANI_ERROR;
+    }
+
+    fsm = &ctx->uFsm.authFsm;
+    if (NULL == fsm) 
+    {
+        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                     "fsm is NULL in %s", __FUNCTION__);
+
+        return ANI_ERROR;
+    }
+
+    if(!VOS_IS_STATUS_SUCCESS( retStatus ) )
+    {
+        //No need to do anything. Retransmit is handled by timeout
+        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+            "Auth: TL Tx complete with error %d current state is %d \n", retStatus, fsm->currentState );
+    }
+    if( PTK_START == fsm->currentState )
+    {
+        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
+            " Auth: start msg2 timer\n" );
+        //Start msg2Timer
+        fsm->numTries++;
+        vos_timer_stop( &fsm->msg2Timer );
+        vos_timer_start(&fsm->msg2Timer, authConsts.timeoutPeriod);
+    }
+    else if( ( PTK_INIT_NEGO == fsm->currentState ) || 
+        ( PTK_INIT_NEGO_TX == fsm->currentState ) )
+    {
+        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
+            " Auth: start msg4 timer\n" );
+        fsm->numTries++;
+        vos_timer_stop( &fsm->msg4Timer );
+        vos_timer_start(&fsm->msg4Timer, authConsts.timeoutPeriod);
+    }
+
+    return ANI_OK;
+}
+
+
+static int
+authEapolKeyHandler( tAuthRsnFsm *fsm, tAniPacket *eapolFrame, tAniMacAddr staMac )
+{
+    int retVal;
+
+    int descType;
+    void *keyDesc;
+    tAniEapolRsnKeyDesc *rsnDesc;
+    tAniEapolKeyAvailEventData data;
+
+    do
+    {
+        retVal = aniEapolParseKey(eapolFrame, &descType, &keyDesc);
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+
+        if ((descType == ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW) 
+                || (descType == ANI_EAPOL_KEY_DESC_TYPE_RSN)) 
+        {
+            rsnDesc = (tAniEapolRsnKeyDesc *) keyDesc;
+            data.keyDesc = keyDesc;
+            data.eapolFrame = eapolFrame;
+            // Pass on the event to the RSN FSM only if it is for a pairwise key
+            if (rsnDesc->info.unicastFlag) 
+            {
+                retVal = authRsnFsmProcessEvent(fsm, 
+                                                RSN_FSM_EAPOL_FRAME_AVAILABLE,
+                                                &data);
+            } 
+            else {
+                //Not worry about GTK stuff
+            }
+        } 
+        else {
+
+            VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                    "Got unexpected legacy 802.1x RC4 Key message \n" );
+            retVal = ANI_E_FAILED;
+            break;
+        }
+    }while( 0 );
+
+    aniEapolKeyFreeDesc(descType, keyDesc);
+    return retVal;
+}
+
+
+void authEapolHandler( tAuthRsnFsm *fsm, tAniPacket *eapolFrame,
+                 tAniMacAddr dstMac, 
+                 tAniMacAddr srcMac,
+                 v_U8_t *type)
+{
+    switch (*type) 
+    {
+    case ANI_EAPOL_TYPE_START:
+        //No doing anything because we only support WPA2-PSK
+        break;
+    case ANI_EAPOL_TYPE_LOGOFF:
+        //ignore
+        break;
+    case ANI_EAPOL_TYPE_KEY:
+        authEapolKeyHandler(fsm, eapolFrame, srcMac);
+        break;
+    default:
+        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+            "Auth: EAPOL type not implemented: 0x%.2x\n", *type);
+        break;
+    }
+}