prima: WLAN Driver Release 3.1.7.9

This is the initial release of the Prima WLAN Driver
diff --git a/CORE/BAP/src/bapRsnSsmEapol.c b/CORE/BAP/src/bapRsnSsmEapol.c
new file mode 100644
index 0000000..6d12fdc
--- /dev/null
+++ b/CORE/BAP/src/bapRsnSsmEapol.c
@@ -0,0 +1,1128 @@
+/*
+ * 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: $Header: //depot/software/projects/feature_branches/gen5_phase1/os/linux/classic/ap/apps/ssm/lib/aniSsmEapol.c#2 $ 
+ *
+ * Contains definitions of various utilities for EAPoL frame
+ * parsing and creation.
+ *
+ * Author:      Mayank D. Upadhyay
+ * Date:        19-June-2002
+ * History:-
+ * Date         Modified by     Modification Information
+ * ------------------------------------------------------
+ *
+ */
+#include "vos_utils.h"
+#include <bapRsnAsfPacket.h>
+#include <bapRsnErrors.h>
+#include <bapRsnSsmEapol.h>
+#include "bapRsn8021xFsm.h"
+#include "vos_memory.h"
+
+//#include "aniSsmUtils.h"
+
+#define CHECK_RETVAL(retVal) \
+              assert(retVal == ANI_OK); \
+              if (retVal != ANI_OK) return ANI_E_FAILED;
+
+
+//TODO: Put these in an array after EAPOL_TYPE is made an enum
+#define ANI_EAPOL_TYPE_PACKET_STR    "EAP"
+#define ANI_EAPOL_TYPE_START_STR     "START"
+#define ANI_EAPOL_TYPE_LOGOFF_STR    "LOGOFF"
+#define ANI_EAPOL_TYPE_KEY_STR       "KEY"
+#define ANI_EAPOL_TYPE_ASF_ALERT_STR "ALERT"
+#define ANI_EAPOL_TYPE_UNKNOWN_STR   "UNKNOWN"
+
+/**
+ * The EAPOL packet is structured as follows:
+ */
+#define DST_MAC_POS 0
+#define SRC_MAC_POS 6
+#define ETHER_PROTO_POS 12
+#define EAPOL_VERSION_POS 14
+#define ANI_EAPOL_TYPE_POS 15
+#define EAPOL_BODY_LEN_POS 16
+#define EAPOL_BODY_POS EAPOL_RX_HEADER_SIZE
+
+#define EAPOL_BODY_LEN_SIZE 2
+
+#define ANI_SSM_LEGACY_RC4_KEY_SIGN_OFFSET EAPOL_BODY_POS + 28
+
+/**
+ * Bitmasks for the RSN Key Information field
+ */
+#define ANI_SSM_RSN_KEY_DESC_VERS_MASK 0x0007
+#define ANI_SSM_RSN_UNICAST_MASK       0x0008
+#define ANI_SSM_RSN_KEY_INDEX_MASK     0x0030
+#define ANI_SSM_RSN_INSTALL_MASK       0x0040
+#define ANI_SSM_RSN_ACK_MASK           0x0080
+#define ANI_SSM_RSN_MIC_MASK           0x0100
+#define ANI_SSM_RSN_SECURE_MASK        0x0200
+#define ANI_SSM_RSN_ERROR_MASK         0x0400
+#define ANI_SSM_RSN_REQUEST_MASK       0x0800
+#define ANI_SSM_RSN_ENC_KEY_DATA_MASK  0x1000
+
+#define ANI_SSM_RSN_KEY_DESC_VERS_OFFSET  0
+#define ANI_SSM_RSN_KEY_INDEX_OFFSET      4
+
+#define ANI_SSM_RSN_KEY_MIC_OFFSET EAPOL_BODY_POS + 77
+
+/**
+ * Other hard coded values for convenience:
+ */
+static const v_U8_t 
+ANI_ETH_P_EAPOL_BYTES[2] = {0x00, 0x03};//BT-AMP security type{0x88, 0x8e};
+static const v_U8_t 
+EAPOL_VERSION_BYTES[1] = {EAPOL_VERSION_1};
+static const v_U8_t 
+ANI_EAPOL_TYPE_PACKET_BYTES[1] = {ANI_EAPOL_TYPE_PACKET};
+static const v_U8_t 
+ANI_EAPOL_TYPE_START_BYTES[1] = {ANI_EAPOL_TYPE_START};
+static const v_U8_t 
+ANI_EAPOL_TYPE_LOGOFF_BYTES[1] = {ANI_EAPOL_TYPE_LOGOFF};
+static const v_U8_t 
+ANI_EAPOL_TYPE_KEY_BYTES[1] = {ANI_EAPOL_TYPE_KEY};
+static const v_U8_t 
+ANI_EAPOL_TYPE_ASF_ALERT_BYTES[1] = {ANI_EAPOL_TYPE_ASF_ALERT};
+static const v_U8_t 
+ZERO_BYTES[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static v_U8_t BAP_RSN_LLC_HEADER[] =  {0xAA, 0xAA, 0x03, 0x00, 0x19, 0x58 };
+
+
+
+static int
+parseRsnKeyDesc(tAniPacket *packet, 
+                tAniEapolRsnKeyDesc **rsnDescPtr);
+
+static int
+parseRsnKeyInfo(tAniPacket *packet, 
+                tAniRsnKeyInfo *info);
+
+static int
+writeRsnKeyDesc(tAniPacket *packet,
+                tAniEapolRsnKeyDesc *rsnDesc,
+                v_U8_t keyDescType);
+
+static int
+writeRsnKeyInfo(tAniPacket *packet, tAniRsnKeyInfo *info);
+
+static int
+writeRsnKeyMic(v_U32_t cryptHandle,
+               tAniPacket *eapolFrame, 
+               tAniEapolRsnKeyDesc *rsnDesc,
+               v_U8_t *micKey, 
+               v_U32_t micKeyLen);
+
+static int
+checkRsnKeyMic(v_U32_t cryptHandle,
+               tAniPacket *eapolFrame,
+               tAniEapolRsnKeyDesc *rsnDesc,
+               v_U8_t *micKey,
+               v_U32_t micKeyLen);
+
+extern void authEapolHandler( tAuthRsnFsm *fsm, tAniPacket *eapolFrame,
+                 tAniMacAddr dstMac, 
+                 tAniMacAddr srcMac,
+                 v_U8_t *type);
+extern void suppEapolHandler( tSuppRsnFsm *fsm, tAniPacket *eapolFrame,
+                 tAniMacAddr dstMac, 
+                 tAniMacAddr srcMac,
+                 v_U8_t *type);
+
+/**
+ * addEapolHeaders
+ *
+ * FUNCTION:
+ * Prepends the EAPOL header to a packet.
+ *
+ * ASSUMPTIONS:
+ * The packet has enough space available for prepending the EAPOL
+ * header.
+ *
+ * @param packet the packet to prepend to
+ * @param dstMac the MAC address of the destination (authenticator)
+ * @param srcMac the MAC address of the source (supplicant)
+ * @param eapolType the EAPOL-Type field
+ *
+ * @return ANI_OK if the operation succeeds
+ */
+static int
+addEapolHeaders(tAniPacket *packet, 
+                tAniMacAddr dstMac, 
+                tAniMacAddr srcMac, 
+                v_U8_t eapolType)
+{
+    int retVal;
+    v_U16_t len;
+  
+    do
+    {
+        retVal = aniAsfPacketGetLen(packet);
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+
+        len = retVal;
+        retVal = aniAsfPacketPrepend16(packet, len);
+
+        retVal = aniAsfPacketPrepend8(packet, eapolType);
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+
+        retVal = aniAsfPacketPrependBuffer(packet, EAPOL_VERSION_BYTES, 1);
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+
+        retVal = aniAsfPacketPrependBuffer(packet, ANI_ETH_P_EAPOL_BYTES, 2);
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+
+        //Since TL expects SNAP header in all packets we send, put it in
+        retVal = aniAsfPacketPrependBuffer(packet, BAP_RSN_LLC_HEADER, sizeof(BAP_RSN_LLC_HEADER));
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+
+        //packet length
+        len += 6/*length + eapolType+version + eth_type*/ + sizeof(BAP_RSN_LLC_HEADER);
+        retVal = aniAsfPacketPrepend16(packet, len);
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+
+        retVal = aniAsfPacketPrependBuffer(packet, srcMac, sizeof(tAniMacAddr));
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+
+        retVal = aniAsfPacketPrependBuffer(packet, dstMac, sizeof(tAniMacAddr));
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+    }while( 0 );
+
+    return retVal;
+}
+
+/**
+ * aniEapolWriteStart
+ *
+ * FUNCTION:
+ * Writes an EAPOL-Start frame to the packet. It is only used by the
+ * supplicant.
+ *
+ * LOGIC:
+ * Prepend the appropriate EAPOL header to the packet. There is no
+ * EAPOL payload for this kind of frame.
+ *
+ * ASSUMPTIONS:
+ * The packet has enough space available for prepending the header.
+ *
+ * @param packet the packet to which the frame should be written
+ * @param dstMac the MAC address of the destination (authenticator)
+ * @param srcMac the MAC address of the source (supplicant)
+ *
+ * @return ANI_OK if the operation succeeds
+ */
+int
+aniEapolWriteStart(tAniPacket *packet, 
+                   tAniMacAddr dstMac,
+                   tAniMacAddr srcMac)
+{
+    return ( addEapolHeaders(packet, dstMac, srcMac, ANI_EAPOL_TYPE_START) );
+}
+
+/**
+ * aniEapolWriteEapPacket
+ *
+ * FUNCTION:
+ * Writes the EAPOL/EAP-Packet frame headers. It is used
+ * by both the authenticator and the supplicant. This creates an EAPOL
+ * frame that is carrying an EAP message as its payload.
+ *
+ * LOGIC:
+ * Prepend the appropriate EAPOL header to the packet.
+ *
+ * ASSUMPTIONS:
+ * The EAP message (ie., the payload) is already available in the
+ * packet and that the packet has enough space available for
+ * prepending the EAPOL header.
+ *
+ * @param packet the packet containing the EAP message
+ * @param dstMac the MAC address of the destination (authenticator)
+ * @param srcMac the MAC address of the source (supplicant)
+ *
+ * @return ANI_OK if the operation succeeds
+ */
+int
+aniEapolWriteEapPacket(tAniPacket *eapPacket, 
+                       tAniMacAddr dstMac, 
+                       tAniMacAddr srcMac)
+{
+    return( addEapolHeaders(eapPacket, dstMac, srcMac, ANI_EAPOL_TYPE_PACKET) );
+}
+
+/**
+ * aniEapolParse
+ *
+ * FUNCTION:
+ * Parses an EAPoL frame to the first level of headers (no EAP
+ * headers are parsed). 
+ *
+ * NOTE: This is a non-destructive read, that is the
+ * headers are not stripped off the packet. However, any additional
+ * data at  the end of the packet, beyond what the EAPoL headers encode
+ * will be stripped off.
+ *
+ * @param packet the packet containing the EAPoL frame to parse
+ * @param dstMac a pointer to set to the location of the destination
+ * MAC address
+ * @param srcMac a pointer to set to the location of the source
+ * MAC address
+ * @param type a pointer to set to the location of the EAPOL type
+ * field.
+ *
+ * @return the non-negative length of the EAPOL payload if the operation
+ * succeeds
+ */
+int 
+aniEapolParse(tAniPacket *packet,
+              v_U8_t **dstMac, 
+              v_U8_t **srcMac, 
+              v_U8_t **type)
+{
+    v_U16_t frameType;
+    v_U8_t *ptr;
+    int retVal;
+    int tmp;
+
+    if (aniAsfPacketGetLen(packet) < EAPOL_BODY_POS)
+        return ANI_E_ILLEGAL_ARG;
+
+    retVal = aniAsfPacketGetBytes(packet, &ptr);
+    if( !ANI_IS_STATUS_SUCCESS( retVal ) )
+    {
+        return retVal;
+    }
+
+    VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
+            "Supp parsing EAPOL packet of len %d: \n",
+                retVal);
+
+    frameType = (ptr[ETHER_PROTO_POS] << 8) + ptr[ETHER_PROTO_POS+1];
+
+    /*
+     * Validate the EAPOL-FRAME
+     */
+
+    if (frameType != ANI_ETH_P_EAPOL)
+        return ANI_E_ILLEGAL_ARG;
+
+    *dstMac = ptr + DST_MAC_POS;
+    *srcMac = ptr + SRC_MAC_POS;
+
+    //    if (ptr[EAPOL_VERSION_POS] != EAPOL_VERSION_1)
+    //        return ANI_E_ILLEGAL_ARG;
+
+    *type = ptr + ANI_EAPOL_TYPE_POS;
+    retVal = (ptr[EAPOL_BODY_LEN_POS] << 8) + ptr[EAPOL_BODY_LEN_POS + 1];
+ 
+    /* 
+     * Validate the length of the body. Allow for longer 
+     * packets than encoded, but encoding should not be larger than
+     * packet.
+     * Note: EAPOL body len does not include headers
+     */
+    tmp = aniAsfPacketGetLen(packet) - EAPOL_RX_HEADER_SIZE;
+    if (retVal > tmp) 
+    {
+        retVal = ANI_E_ILLEGAL_ARG;
+    } 
+    else {
+        if (retVal < tmp) 
+        {
+            retVal = aniAsfPacketTruncateFromRear(packet, tmp - retVal);
+        }
+    }
+
+    return retVal;
+}
+
+/**
+ * aniEapolWriteKey
+ *
+ * Writes out a complete EAPOL-Key frame. The key descriptor is
+ * appended to the packet and the EAPOL header is prepended to it. If
+ * a micKey is passed in, then a MIC is calculated and inserted into
+ * the frame.
+ *
+ * @param packet the packet to write to
+ * @param dstMac the destination MAC address
+ * @param srcMac the source MAC address
+ * @param descType the key descriptor type
+ * (ANI_EAPOL_KEY_DESC_TYPE_LEGACY_RC4 or
+ * ANI_EAPOL_KEY_DESC_TYPE_RSN).
+ * @param keyDescData the key descriptor data corresponding to the
+ * above descType. The signature field is ignored and will be
+ * generated in the packet. The key bytes are expected to be encrypted
+ * if they need to be encrypted.
+ * @param micKey the MIC key
+ * @param micKeyLen the number of bytes in the MIC key
+ *
+ * @return ANI_OK if the operation succeeds
+ *
+ */
+int
+aniEapolWriteKey(v_U32_t cryptHandle,
+                 tAniPacket *packet,
+                 tAniMacAddr dstMac, 
+                 tAniMacAddr srcMac, 
+                 int descType,
+                 void *keyDescData,
+                 v_U8_t *micKey,
+                 v_U32_t micKeyLen)
+{
+    int retVal;
+
+    if (packet == NULL)
+        return ANI_E_NULL_VALUE;
+
+    do
+    {
+        if ((descType == ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW) 
+                || (descType == ANI_EAPOL_KEY_DESC_TYPE_RSN)) 
+        {
+
+            retVal = writeRsnKeyDesc(packet,
+                                     (tAniEapolRsnKeyDesc *) keyDescData,
+                                     // Indicate 
+                                     // ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW 
+                                     // or ANI_EAPOL_KEY_DESC_TYPE_RSN
+                                     descType);
+            if( !ANI_IS_STATUS_SUCCESS( retVal ) )
+            {
+                break;
+            }
+
+            retVal = addEapolHeaders(packet, dstMac, srcMac, ANI_EAPOL_TYPE_KEY);
+            if( !ANI_IS_STATUS_SUCCESS(retVal) ) break;
+
+            retVal = writeRsnKeyMic(cryptHandle,
+                                    packet, 
+                                    (tAniEapolRsnKeyDesc *) keyDescData,
+                                    micKey, micKeyLen);
+            if( !ANI_IS_STATUS_SUCCESS(retVal) ) break;
+
+        } 
+        else {
+            VOS_ASSERT( 0 );
+            return ANI_E_ILLEGAL_ARG;
+        }
+    }while( 0 );
+
+    return retVal;
+}
+
+
+/**
+ * aniEapolParseKey
+ *
+ * Parses and verifies a complete EAPOL-Key frame. The key descriptor
+ * type is returned and so is a newly allocated key descriptor structure
+ * that is appropriate for the type.
+ *
+ * NOTE: This is a non-destructive read. That is, the packet headers
+ * will be unchanged at the end of this read operation. This is so
+ * that a followup MIC check may be done on the complete packet. If
+ * the packet parsing fails, the packet headers are not guaranteed to
+ * be unchanged.
+ *
+ * @param packet the packet to read from. Note that the frame is not
+ * expected to contain any additional padding at the end other than
+ * the exact number of key bytes. (The aniEapolParse function will
+ * ensure this.)
+ * @param descType is set to the key descriptor type
+ * (ANI_EAPOL_KEY_DESC_TYPE_LEGACY_RC4 or
+ * ANI_EAPOL_KEY_DESC_TYPE_RSN).
+ * @param keyDescData is set to a newly allocated key descriptor
+ * corresponding to the above descType. The signature field is
+ * verified. The key bytes will be returned encrypted. It is the
+ * responsibility of the caller to free this structure and the data
+ * contained therein.
+ *
+ * @return ANI_OK if the operation succeeds
+ */
+int
+aniEapolParseKey(tAniPacket *packet,
+                 int *descType,
+                 void **keyDescData)
+{
+    int retVal;
+    v_U8_t *bytes;
+    v_U32_t eapolFrameLen;
+
+    if (packet == NULL)
+        return ANI_E_NULL_VALUE;
+
+    do
+    {
+        eapolFrameLen = aniAsfPacketGetLen(packet);
+
+        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO, "Supp parsing EAPOL-Key frame of len %d\n", 
+                      eapolFrameLen);
+
+        retVal = aniAsfPacketTruncateFromFront(packet, EAPOL_RX_HEADER_SIZE);
+        if( !ANI_IS_STATUS_SUCCESS(retVal) ) break;
+        
+        retVal = aniAsfPacketGetBytes(packet, &bytes);
+        if( !ANI_IS_STATUS_SUCCESS(retVal) ) break;
+
+        if (*bytes == ANI_EAPOL_KEY_DESC_TYPE_RSN ||
+                   *bytes == ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW) 
+        {
+            tAniEapolRsnKeyDesc *rsnDesc = NULL;
+
+            //*descType = ANI_EAPOL_KEY_DESC_TYPE_RSN;
+            *descType = (*bytes == ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW ?  
+                 ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW :  ANI_EAPOL_KEY_DESC_TYPE_RSN) ;
+            retVal = parseRsnKeyDesc(packet, &rsnDesc);
+            if( !ANI_IS_STATUS_SUCCESS(retVal) ) break;
+            *keyDescData = rsnDesc;
+        } 
+        else 
+        {
+            VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, 
+                "Supp received unknown EAPOL-Key descriptor: %d\n",
+                        *bytes);
+            retVal = ANI_E_ILLEGAL_ARG;
+            break;
+        }
+
+        aniAsfPacketMoveLeft(packet, eapolFrameLen);
+    }while( 0 );
+    
+    return retVal;
+}
+
+
+
+static int
+parseRsnKeyDesc(tAniPacket *packet, 
+                tAniEapolRsnKeyDesc **rsnDescPtr)
+{
+    int retVal = ANI_OK;
+    int len;
+    v_U8_t *bytes;
+    tAniEapolRsnKeyDesc *rsnDesc = NULL;
+
+    do
+    {
+        aniAsfPacketTruncateFromFront(packet, 1); // Desc-Type
+
+        rsnDesc = (tAniEapolRsnKeyDesc *) 
+            vos_mem_malloc( sizeof(tAniEapolRsnKeyDesc) );
+
+        if (rsnDesc == NULL) 
+        {
+            VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                    "Supp could not malloc EAPOL-Key Descriptor for RSN\n");
+            retVal = ANI_E_MALLOC_FAILED;
+            break;
+        }
+
+        retVal = parseRsnKeyInfo(packet, &rsnDesc->info);
+        if (retVal != ANI_OK) break;
+
+        retVal = aniAsfPacketGet16(packet, &rsnDesc->keyLen);
+        if (retVal != ANI_OK)
+        {
+            break;
+        }
+
+        len = sizeof(rsnDesc->replayCounter);
+        retVal = aniAsfPacketGetN(packet, len, &bytes);
+        if (retVal != ANI_OK)
+        {
+            break;
+        }
+        vos_mem_copy(rsnDesc->replayCounter, bytes, len);
+
+        len = sizeof(rsnDesc->keyNonce);
+        retVal = aniAsfPacketGetN(packet, len, &bytes);
+        if (retVal != ANI_OK)
+        {
+            break;
+        }
+        vos_mem_copy(rsnDesc->keyNonce, bytes, len);
+
+        len = sizeof(rsnDesc->keyIv);
+        retVal = aniAsfPacketGetN(packet, len, &bytes);
+        if (retVal != ANI_OK)
+        {
+            break;
+        }
+        vos_mem_copy(rsnDesc->keyIv, bytes, len);
+
+        len = sizeof(rsnDesc->keyRecvSeqCounter);
+        retVal = aniAsfPacketGetN(packet, len, &bytes);
+        if (retVal != ANI_OK)
+        {
+            break;
+        }
+        vos_mem_copy(rsnDesc->keyRecvSeqCounter, bytes, len);    
+
+        len = sizeof(rsnDesc->keyId);
+        retVal = aniAsfPacketGetN(packet, len, &bytes);
+        if (retVal != ANI_OK)
+        {
+            break;
+        }
+        vos_mem_copy(rsnDesc->keyId, bytes, len);
+
+        len = sizeof(rsnDesc->keyMic);
+        retVal = aniAsfPacketGetN(packet, len, &bytes);
+        if (retVal != ANI_OK)
+        {
+            break;
+        }
+        vos_mem_copy(rsnDesc->keyMic, bytes, len);
+
+        retVal = aniAsfPacketGet16(packet, &rsnDesc->keyDataLen);
+        if (retVal != ANI_OK)
+        {
+            break;
+        }
+
+        len = rsnDesc->keyDataLen;
+        if (len > 0) {
+            // We have a key
+            retVal = aniAsfPacketGetN(packet, len, &bytes);
+            if (retVal != ANI_OK)
+            {
+             break;
+            }
+            rsnDesc->keyData = (v_U8_t*)vos_mem_malloc(len);
+            if (rsnDesc->keyData == NULL) 
+            {
+                VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "Could not allocate RSN key bytes!\n");
+                VOS_ASSERT( 0 );
+                retVal = ANI_E_MALLOC_FAILED;
+                break;
+            }
+            vos_mem_copy(rsnDesc->keyData, bytes, len);
+        } 
+        else {
+            rsnDesc->keyData = NULL;
+        }
+
+        *rsnDescPtr = rsnDesc;
+
+    }while( 0 );
+
+    if( !ANI_IS_STATUS_SUCCESS( retVal ) )
+    {
+        vos_mem_free(rsnDesc);
+    }
+
+    return retVal;
+}
+
+static int
+parseRsnKeyInfo(tAniPacket *packet, 
+                tAniRsnKeyInfo *info)
+{
+    v_U16_t tmp;
+    int retVal;
+
+    retVal = aniAsfPacketGet16(packet, &tmp);
+    if( !ANI_IS_STATUS_SUCCESS( retVal ) )
+    {
+        return retVal;
+    }
+
+    info->keyDescVers = (tmp & ANI_SSM_RSN_KEY_DESC_VERS_MASK) 
+        >> ANI_SSM_RSN_KEY_DESC_VERS_OFFSET;
+    if (info->keyDescVers != ANI_EAPOL_KEY_DESC_VERS_RC4 &&
+        info->keyDescVers != ANI_EAPOL_KEY_DESC_VERS_AES)
+        return ANI_E_ILLEGAL_ARG;
+
+    info->unicastFlag = (tmp & ANI_SSM_RSN_UNICAST_MASK) ? 
+        eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE;
+    info->keyId    = (tmp & ANI_SSM_RSN_KEY_INDEX_MASK)
+        >> ANI_SSM_RSN_KEY_INDEX_OFFSET;
+    info->installFlag = (tmp & ANI_SSM_RSN_INSTALL_MASK) ?
+        eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE;
+    info->ackFlag     = (tmp & ANI_SSM_RSN_ACK_MASK) ?
+        eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE;
+    info->micFlag     = (tmp & ANI_SSM_RSN_MIC_MASK) ?
+        eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE;
+    info->secureFlag  = (tmp & ANI_SSM_RSN_SECURE_MASK) ?
+        eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE;
+    info->errorFlag   = (tmp & ANI_SSM_RSN_ERROR_MASK) ?
+        eANI_BOOLEAN_TRUE: eANI_BOOLEAN_FALSE;
+    info->requestFlag = (tmp & ANI_SSM_RSN_REQUEST_MASK) ?
+        eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE;
+    info->encKeyDataFlag = (tmp & ANI_SSM_RSN_ENC_KEY_DATA_MASK) ?
+        eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE;
+
+    return ANI_OK;
+}
+
+
+static int
+writeRsnKeyDesc(tAniPacket *packet, 
+                tAniEapolRsnKeyDesc *rsnDesc,
+                v_U8_t keyDescType)
+{
+    int retVal;
+
+    do
+    {
+        // This can be either ANI_EAPOL_KEY_DESC_TYPE_RSN
+        // or ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW
+        retVal = aniAsfPacketAppend8(packet, keyDescType);
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+
+        retVal = writeRsnKeyInfo(packet, &rsnDesc->info);
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+
+        retVal = aniAsfPacketAppend16(packet, rsnDesc->keyLen);
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+
+        retVal = aniAsfPacketAppendBuffer(packet, 
+                                          rsnDesc->replayCounter,
+                                          sizeof(rsnDesc->replayCounter));
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+
+        retVal = aniAsfPacketAppendBuffer(packet, 
+                                          rsnDesc->keyNonce, 
+                                          sizeof(rsnDesc->keyNonce));
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+
+        retVal = aniAsfPacketAppendBuffer(packet, 
+                                          rsnDesc->keyIv, 
+                                          sizeof(rsnDesc->keyIv));
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+
+        retVal = aniAsfPacketAppendBuffer(packet, 
+                                          rsnDesc->keyRecvSeqCounter, 
+                                          sizeof(rsnDesc->keyRecvSeqCounter));
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+
+        retVal = aniAsfPacketAppendBuffer(packet, 
+                                          rsnDesc->keyId, 
+                                          sizeof(rsnDesc->keyId));
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+
+        // Zero out the key MIC
+        retVal = aniAsfPacketAppendBuffer(packet, 
+                                          ZERO_BYTES, 
+                                          sizeof(rsnDesc->keyMic));
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+
+        retVal = aniAsfPacketAppend16(packet, rsnDesc->keyDataLen);
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+
+        if (rsnDesc->keyDataLen != 0) 
+        {
+            retVal = aniAsfPacketAppendBuffer(packet, 
+                                              rsnDesc->keyData, 
+                                              rsnDesc->keyDataLen);
+            if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+        }
+    }while( 0 );
+
+    return retVal;
+}
+
+static int
+writeRsnKeyInfo(tAniPacket *packet, tAniRsnKeyInfo *info)
+{
+    int retVal;
+    v_U16_t tmp;
+    v_U16_t infoValue;
+
+    infoValue = 0;
+
+    tmp = (v_U16_t)info->keyDescVers;
+    tmp = tmp << ANI_SSM_RSN_KEY_DESC_VERS_OFFSET;
+    infoValue |= (tmp & ANI_SSM_RSN_KEY_DESC_VERS_MASK);
+
+    if (info->unicastFlag)
+        infoValue |= ANI_SSM_RSN_UNICAST_MASK;
+
+    tmp = info->keyId;
+    tmp = tmp << ANI_SSM_RSN_KEY_INDEX_OFFSET;
+    infoValue |= (tmp & ANI_SSM_RSN_KEY_INDEX_MASK);
+
+    if (info->installFlag)
+        infoValue |= ANI_SSM_RSN_INSTALL_MASK;
+
+    if (info->ackFlag)
+        infoValue |= ANI_SSM_RSN_ACK_MASK;
+
+    if (info->micFlag)
+        infoValue |= ANI_SSM_RSN_MIC_MASK;
+
+    if (info->secureFlag)
+        infoValue |= ANI_SSM_RSN_SECURE_MASK;
+
+    if (info->errorFlag)
+        infoValue |= ANI_SSM_RSN_ERROR_MASK;
+
+    if (info->requestFlag)
+        infoValue |= ANI_SSM_RSN_REQUEST_MASK;
+    
+    if (info->encKeyDataFlag)
+        infoValue |= ANI_SSM_RSN_ENC_KEY_DATA_MASK;
+    
+    retVal = aniAsfPacketAppend16(packet, infoValue);
+
+    return retVal;
+}
+
+
+static int
+writeRsnKeyMic(v_U32_t cryptHandle,
+               tAniPacket *eapolFrame, 
+               tAniEapolRsnKeyDesc *rsnDesc,
+               v_U8_t *micKey, 
+               v_U32_t micKeyLen)
+{
+    int retVal = ANI_OK;
+    int len;
+
+    v_U8_t *ptr = NULL;
+    v_U8_t *micPos = NULL;
+    v_U8_t result[VOS_DIGEST_SHA1_SIZE]; // Larger of the two
+
+    // Sanity check the arguments and return if no MIC generation is
+    // needed
+    if (micKey != NULL) 
+    {
+        if (micKeyLen == 0 || !rsnDesc->info.micFlag) 
+        {
+            VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                "Supp MIC key provided but micKeyLen or micFlag is not set!\n");
+            VOS_ASSERT( 0 );
+            return ANI_E_ILLEGAL_ARG;
+        }
+    } 
+    else {
+        if (rsnDesc->info.micFlag) 
+        {
+            VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                "Supp micFlag is set but MIC key not provided!\n");
+            VOS_ASSERT( 0 );
+            return ANI_E_ILLEGAL_ARG;
+        }
+        // Normal condition where MIC is not desired by the caller
+        return ANI_OK;
+    }
+
+    len = aniAsfPacketGetBytes(eapolFrame, &ptr);
+    if( !ANI_IS_STATUS_SUCCESS( len ) )
+    {
+        return len;
+    }
+
+    micPos = ptr + ANI_SSM_RSN_KEY_MIC_OFFSET + SNAP_HEADER_SIZE;
+
+    // Clear the MIC field in the packet before the MIC computation
+    vos_mem_zero( micPos, VOS_DIGEST_MD5_SIZE);
+
+    // Skip to the EAPOL version field for MIC computation
+    ptr += EAPOL_VERSION_POS + SNAP_HEADER_SIZE;
+    len -= (EAPOL_VERSION_POS + SNAP_HEADER_SIZE);
+
+    if (rsnDesc->info.keyDescVers == ANI_EAPOL_KEY_DESC_VERS_AES) 
+    {
+        if( VOS_IS_STATUS_SUCCESS( vos_sha1_hmac_str(cryptHandle, ptr, len, micKey, micKeyLen, result) ) )
+        {
+            retVal = ANI_OK;
+        }
+        else
+        {
+            retVal = ANI_ERROR;
+        }
+    } 
+    else {
+        VOS_ASSERT( 0 );
+        retVal = ANI_E_ILLEGAL_ARG;
+    }
+
+    if (retVal == ANI_OK) 
+    {
+        // Copy only 16B which is the smaller of the two and the same as
+        // ANI_EAPOL_KEY_RSN_MIC_SIZE
+        vos_mem_copy(micPos, result, VOS_DIGEST_MD5_SIZE);
+    }
+
+    return retVal;
+}
+
+/**
+ * aniEapolKeyCheckMic
+ *
+ * @param eapolFrame the complete EAPOL-Key packet
+ * @param descType the key descriptor type
+ * @param keyDescData the key descriptor
+ * @param micKey the MIC key
+ * @param micKeyLen the number of bytes in the MIC key
+ *
+ * @return ANI_OK if the operation succeeds; ANI_E_MIC_FAILED if the
+ * MIC check fails.
+ */
+int
+aniEapolKeyCheckMic(v_U32_t cryptHandle,
+                    tAniPacket *eapolFrame,
+                    int descType,
+                    void *keyDescData,
+                    v_U8_t *micKey,
+                    v_U32_t micKeyLen)
+{
+    if (descType == ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW) 
+    {
+        return checkRsnKeyMic(cryptHandle, eapolFrame, keyDescData, micKey, micKeyLen);
+    } 
+    else {
+        VOS_ASSERT( 0 );
+        return ANI_E_ILLEGAL_ARG;
+    }
+}
+
+
+static int
+checkRsnKeyMic(v_U32_t cryptHandle,
+               tAniPacket *eapolFrame,
+               tAniEapolRsnKeyDesc *rsnDesc,
+               v_U8_t *micKey,
+               v_U32_t micKeyLen) 
+{
+    int retVal = ANI_ERROR;
+    int len;
+
+    v_U8_t *ptr = NULL;
+    v_U8_t *micPos = NULL;
+
+    v_U8_t result[VOS_DIGEST_SHA1_SIZE]; // Larger of the two
+    v_U8_t incomingMic[ANI_EAPOL_KEY_RSN_MIC_SIZE];
+
+    if (!rsnDesc->info.micFlag) 
+    {
+        VOS_ASSERT( 0 );
+        return ANI_E_ILLEGAL_ARG;
+    }
+
+    len = aniAsfPacketGetBytes(eapolFrame, &ptr);
+    if( ANI_IS_STATUS_SUCCESS( len ) )
+    {
+        micPos = ptr + ANI_SSM_RSN_KEY_MIC_OFFSET;
+
+        // Skip to the EAPOL version field for MIC computation
+        ptr += EAPOL_VERSION_POS;
+        len -= EAPOL_VERSION_POS;
+
+        // Copy existing MIC to temporary location and zero it out
+        vos_mem_copy( incomingMic, micPos, ANI_EAPOL_KEY_RSN_MIC_SIZE );
+        vos_mem_zero( micPos, ANI_EAPOL_KEY_RSN_MIC_SIZE );
+
+        if (rsnDesc->info.keyDescVers == ANI_EAPOL_KEY_DESC_VERS_AES) 
+        {
+            if( VOS_IS_STATUS_SUCCESS( vos_sha1_hmac_str(cryptHandle, ptr, len, micKey, micKeyLen, result) ) )
+            {
+                retVal = ANI_OK;
+            }
+        } 
+        else {
+            VOS_ASSERT( 0 );
+            retVal = ANI_E_ILLEGAL_ARG;
+        }
+
+        if (retVal == ANI_OK) 
+        {
+            if ( !vos_mem_compare(incomingMic, result, ANI_EAPOL_KEY_RSN_MIC_SIZE))
+            {
+                retVal = ANI_E_MIC_FAILED;
+            }
+        }
+    }
+
+    return retVal;
+}
+
+/**
+ * aniEapolKeyFreeDesc
+ *
+ * Frees the EAPOL key descriptor and the key bytes contained within it.
+ *
+ * @param descType the key descriptor type
+ * @param keyDescData the key descriptor
+ *
+ * @return ANI_OK if the operation succeeds
+ */
+int
+aniEapolKeyFreeDesc(int descType, void *keyDescData)
+{
+    tAniEapolRsnKeyDesc *rsnDesc;
+
+    if( keyDescData )
+    {
+        if ((descType == ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW) 
+                || (descType == ANI_EAPOL_KEY_DESC_TYPE_RSN)) 
+        {
+
+            rsnDesc = (tAniEapolRsnKeyDesc *) keyDescData;
+            if (rsnDesc->keyData != NULL)
+                vos_mem_free(rsnDesc->keyData);
+
+        } 
+        else {
+
+            VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                "Supp asked to free illegal type: %d\n", descType);
+
+        }
+
+        vos_mem_free(keyDescData);
+    }
+
+    return ANI_OK;
+}
+
+v_U8_t *
+aniEapolType2Str(v_U8_t type)
+{
+    switch (type) 
+    {
+    case ANI_EAPOL_TYPE_PACKET:
+        return (v_U8_t *)ANI_EAPOL_TYPE_PACKET_STR;
+        break;
+    case ANI_EAPOL_TYPE_START:
+        return (v_U8_t *)ANI_EAPOL_TYPE_START_STR;
+        break;
+    case ANI_EAPOL_TYPE_LOGOFF:
+        return (v_U8_t *)ANI_EAPOL_TYPE_LOGOFF_STR;
+        break;
+    case ANI_EAPOL_TYPE_KEY:
+        return (v_U8_t *)ANI_EAPOL_TYPE_KEY_STR;
+        break;
+    case ANI_EAPOL_TYPE_ASF_ALERT:
+        return (v_U8_t *)ANI_EAPOL_TYPE_ASF_ALERT_STR;
+        break;
+    default:
+        return (v_U8_t *)ANI_EAPOL_TYPE_UNKNOWN_STR;
+        break;
+    }
+}
+
+
+void bapRsnEapolHandler( v_PVOID_t pvFsm, tAniPacket *packet, v_BOOL_t fIsAuth )
+{
+    int retVal;
+    v_U8_t *dstMac = NULL;
+    v_U8_t *srcMac = NULL;
+    v_U8_t *type = NULL;
+
+    retVal = aniEapolParse(packet, &dstMac, &srcMac, &type);
+    if ( retVal >= 0 )
+    {
+        retVal = ANI_OK;
+
+        // Sanity check that a PAE role has been assigned to it,
+        // and then dispatch to the appropriate handler
+
+        if( fIsAuth )
+        {
+            tAuthRsnFsm *fsm = (tAuthRsnFsm *)pvFsm;
+            authEapolHandler( fsm, packet, dstMac, srcMac, type );
+        }
+        else
+        {
+            tSuppRsnFsm *fsm = (tSuppRsnFsm *)pvFsm;
+            suppEapolHandler(fsm, packet, dstMac, srcMac, type);
+        } // switch statement
+    } // Successfully parsed EAPOL
+    else
+    {
+        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+            "eapolHandler Received bad EAPOL message of len %d (status=%d)\n",
+                      aniAsfPacketGetLen(packet), retVal );
+    } 
+    aniAsfPacketFree( packet );
+}
+
+
+int bapRsnFormPktFromVosPkt( tAniPacket **ppPacket, vos_pkt_t *pVosPacket )
+{
+    int retVal = ANI_ERROR;
+    VOS_STATUS status;
+    v_U16_t uPktLen;
+#define BAP_RSN_SNAP_TYPE_OFFSET 20
+#define BAP_RSN_ETHERNET_3_HEADER_LEN   22
+    v_U8_t *pFrame;
+    tAniPacket *pAniPacket = NULL;
+
+    do
+    {
+        status = vos_pkt_get_packet_length( pVosPacket, &uPktLen );
+        if( !VOS_IS_STATUS_SUCCESS(status) ) break;
+        if( (uPktLen < BAP_RSN_ETHERNET_3_HEADER_LEN) )
+        {
+            VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                " authRsnRxFrameHandler receive eapol packet size (%d) too small (%d)\n", 
+                uPktLen, BAP_RSN_ETHERNET_3_HEADER_LEN );
+            break;
+        }
+        status = vos_pkt_peek_data( pVosPacket, 0, (v_VOID_t *)&pFrame, uPktLen );
+        if( !VOS_IS_STATUS_SUCCESS(status) ) break;
+        retVal = aniAsfPacketAllocateExplicit(&pAniPacket, uPktLen, 0 );
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) )
+        {
+            VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                " authRsnRxFrameHandler failed to get buffer size (%d) \n", 
+                uPktLen );
+            break;
+        }
+        aniAsfPacketEmptyExplicit( pAniPacket, 0 );
+        pFrame[ETHER_PROTO_POS] = pFrame[BAP_RSN_SNAP_TYPE_OFFSET];
+        pFrame[ETHER_PROTO_POS + 1] = pFrame[BAP_RSN_SNAP_TYPE_OFFSET + 1];
+        //push ethernet II header in
+        retVal = aniAsfPacketAppendBuffer( pAniPacket, pFrame, ETHER_PROTO_POS + 2 );
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
+        //Get the rest of the data in
+        uPktLen -= BAP_RSN_ETHERNET_3_HEADER_LEN;
+        VOS_ASSERT( uPktLen > 0 );
+        retVal = aniAsfPacketAppendBuffer( pAniPacket, pFrame + BAP_RSN_ETHERNET_3_HEADER_LEN, 
+                            uPktLen );
+        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) 
+        {
+            VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
+                " authRsnRxFrameHandler cannot retrieve eapol payload size (%d)\n", 
+                uPktLen );
+            break;
+        }
+    }while( 0 );
+
+    if( ANI_IS_STATUS_SUCCESS( retVal ) )
+    {
+        *ppPacket = pAniPacket;
+    }
+    else if( pAniPacket )
+    {
+        aniAsfPacketFree( pAniPacket );
+    }
+
+    return retVal;
+}
+
+