示例#1
0
/**
 * 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;
}
示例#2
0
/**
 * 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;
}
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 checkInfoElement(tSuppRsnFsm *fsm,
                            tAniEapolKeyAvailEventData *data)
{
    tAniEapolRsnKeyDesc *desc;
    v_U8_t *ieApBytes;
    int ieApLen;

    desc = (tAniEapolRsnKeyDesc *) data->keyDesc;
    if( NULL == desc )
    {
        return ANI_E_NULL_VALUE;
    }

    ieApLen = aniAsfPacketGetBytes(fsm->suppCtx->ieAp, &ieApBytes);
    if( ANI_IS_STATUS_SUCCESS( ieApLen ) )
    {

        if ((desc->keyDataLen != ieApLen) ||
            ( vos_mem_compare(desc->keyData, ieApBytes, ieApLen) )) 
        {
            // TODO: Send a fault here
            VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, 
                         "Supp AP sent inconsistent RSN IE!\n" );
            return ANI_E_FAILED;
        }
    }

    return ANI_OK;
}
示例#5
0
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;
}
//
//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", __func__);

        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", __func__);

        return retVal;
    }

    fsm = &ctx->uFsm.authFsm;
    if (NULL == fsm) 
    {
        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
                     "fsm is NULL in %s", __func__);

        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;
}
int
aagPtkPrf(v_U32_t cryptHandle,
          v_U8_t result[AAG_PRF_MAX_OUTPUT_SIZE],
          v_U32_t prfLen,
          tAniPacket *pmk, 
          tAniMacAddr authAddr,
          tAniMacAddr suppAddr,
          v_U8_t aNonce[ANI_EAPOL_KEY_RSN_NONCE_SIZE],
          v_U8_t sNonce[ANI_EAPOL_KEY_RSN_NONCE_SIZE])
{
    v_U8_t *lowMac;
    v_U8_t *highMac;
    v_U8_t *lowNonce;
    v_U8_t *highNonce;

    v_U8_t *keyBytes;
    int keyLen;

    v_U8_t text[AAG_PTK_PRF_TEXT_LEN];

    
    if (vos_mem_compare2(authAddr, suppAddr, sizeof(tAniMacAddr)) < 0) {
        lowMac = authAddr;
        highMac = suppAddr;
    } else {
        lowMac = suppAddr;
        highMac = authAddr;
    }

    if (vos_mem_compare2(aNonce, sNonce, ANI_EAPOL_KEY_RSN_NONCE_SIZE) < 0) {
        lowNonce = aNonce;
        highNonce = sNonce;
    } else {
        lowNonce = sNonce;
        highNonce = aNonce;
    }

    vos_mem_copy(text + AAG_PTK_PRF_LM_POS, lowMac, sizeof(tAniMacAddr));
    vos_mem_copy(text + AAG_PTK_PRF_HM_POS, highMac, sizeof(tAniMacAddr));
    vos_mem_copy(text + AAG_PTK_PRF_LN_POS, lowNonce, ANI_EAPOL_KEY_RSN_NONCE_SIZE);
    vos_mem_copy(text + AAG_PTK_PRF_HN_POS, highNonce, ANI_EAPOL_KEY_RSN_NONCE_SIZE);

    keyLen = aniAsfPacketGetBytes(pmk, &keyBytes);
    if( !ANI_IS_STATUS_SUCCESS( keyLen ) )
    {
        return keyLen;
    }

    return aagPrf(cryptHandle,
                  result, 
                  keyBytes, keyLen, 
                  (v_U8_t *)AAG_PTK_PRF_CONST, AAG_PTK_PRF_CONST_LEN,
                  text, sizeof(text),
                  prfLen);
}
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];


    if (frameType != ANI_ETH_P_EAPOL)
        return ANI_E_ILLEGAL_ARG;

    *dstMac = ptr + DST_MAC_POS;
    *srcMac = ptr + SRC_MAC_POS;

    
    

    *type = ptr + ANI_EAPOL_TYPE_POS;
    retVal = (ptr[EAPOL_BODY_LEN_POS] << 8) + ptr[EAPOL_BODY_LEN_POS + 1];
 
    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;
}
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;

        
        retVal = aniAsfPacketPrependBuffer(packet, BAP_RSN_LLC_HEADER, sizeof(BAP_RSN_LLC_HEADER));
        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;

        
        len += 6 + 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;
}
示例#10
0
/**
 * 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;
}
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;
}
static int
suppEapolKeyHandler( tSuppRsnFsm *fsm,
                    tAniPacket *eapolFrame, 
                    tAniMacAddr suppMac)
{
    int retVal;
    
    int descType;
    void *keyDesc;
    tAniEapolRsnKeyDesc *rsnDesc;
    tAniEapolKeyAvailEventData data;

    do
    {
        retVal = aniEapolParseKey(eapolFrame, &descType, &keyDesc);
        if( !ANI_IS_STATUS_SUCCESS( retVal ) )
        {
            return retVal;
        }

        if (descType == ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW) 
        {
            rsnDesc = (tAniEapolRsnKeyDesc *) keyDesc;
            /*
             * Pass on the event to the RSN FSM irrespective if it is
             * pairwise or not.
             */
            data.keyDesc = keyDesc;
            data.eapolFrame = eapolFrame;
            retVal = suppRsnFsmProcessEvent(fsm, 
                                            RSN_FSM_EAPOL_FRAME_AVAILABLE,
                                            &data);
        } 
        else {
            VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
                "Supp: Got unexpected 802.1x RC4 Key message \n" );
            retVal = ANI_E_FAILED;
            break;
        }
    }while( 0 );

    aniEapolKeyFreeDesc(descType, keyDesc);
    return retVal;
}
示例#13
0
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 checkTransition(tSuppRsnFsm *fsm, void *arg)
{
    tAniEapolKeyAvailEventData *data;
    tAniEapolRsnKeyDesc *rxDesc;
    v_BOOL_t retransmit;
    int retVal;

    if (fsm->authReq) 
    {
        gotoStateAuthentication(fsm);
        return ANI_OK;
    }

    switch (fsm->currentState) 
    {
    case INITIALIZE:
        break;
    case AUTHENTICATION:
        gotoStateGotPmk(fsm);
        checkTransition(fsm, arg);
        break;
    case GOT_PMK:
        if (fsm->eapolAvail) {

            fsm->eapolAvail = eANI_BOOLEAN_FALSE;
            data = (tAniEapolKeyAvailEventData *) arg;
            rxDesc = (tAniEapolRsnKeyDesc *) data->keyDesc;

            if (rxDesc->info.ackFlag) 
            {

                aniSsmReplayCtrUpdate(fsm->peerReplayCtr,
                                      rxDesc->replayCounter);

                // Going from one state to another cannot be a retransmit
                retVal = gotoStateStaKeyStart(fsm, data, eANI_BOOLEAN_FALSE);

            }
        }
        break;
    case STA_KEY_START:
        if (fsm->eapolAvail) {

            fsm->eapolAvail = eANI_BOOLEAN_FALSE;
            data = (tAniEapolKeyAvailEventData *) arg;
            rxDesc = (tAniEapolRsnKeyDesc *) data->keyDesc;

            if (rxDesc->info.ackFlag) {

                retVal = checkPeerReplayCounter(
                        fsm, 
                        data, 
                        &retransmit, 
                        rxDesc->info.micFlag,
                        0);  // MIC not set means check for re-Tx M1.
                if (retVal != ANI_OK)
                    return ANI_OK; // Caller should not fail

                if (retransmit) {

                    VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
                                    "Resending EAPOL-Key Msg2 from "
                                  "supplicant to AP" );
                    retVal = gotoStateStaKeyStart(fsm, data, eANI_BOOLEAN_TRUE);

                } 
                else {
                    retVal = checkMic(fsm, data, rxDesc->info.unicastFlag);
                    if (retVal != ANI_OK) 
                    {
                        bapSuppDisconnect( fsm->ctx );
                        return retVal;
                    }

                    aniSsmReplayCtrUpdate(fsm->peerReplayCtr,
                                          rxDesc->replayCounter);

                    gotoStateStaKeySet(fsm, data, eANI_BOOLEAN_FALSE);

                }
            }
        }
        break;
    case STA_KEY_SET:
        if (fsm->eapolAvail) 
        {
            fsm->eapolAvail = eANI_BOOLEAN_FALSE;
            data = (tAniEapolKeyAvailEventData *) arg;
            rxDesc = (tAniEapolRsnKeyDesc *) data->keyDesc;

            retVal = checkPeerReplayCounter(
                        fsm, 
                        data, 
                        &retransmit, 
                        rxDesc->info.micFlag,
                        1);  // MIC set means check for re-Tx M3.
            if (retVal != ANI_OK)
                return ANI_OK; // Caller should not fail

            if (!retransmit) 
            {
                retVal = checkMic(fsm, data, rxDesc->info.unicastFlag);
                if (retVal != ANI_OK) 
                {
                    bapSuppDisconnect( fsm->ctx );
                    return retVal;
                }
                aniSsmReplayCtrUpdate(fsm->peerReplayCtr,
                                      rxDesc->replayCounter);

            }

            if (rxDesc->info.unicastFlag) 
            {
                /* 
                 * Handle pairwise key message...in this state
                 * pairwise key messages can only be for retransmissions.
                 */
                if (retransmit) 
                {
                    VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, 
                                   "Resending EAPOL-Key Msg4 from "
                                  "supplicant \n" );
                    retVal = gotoStateStaKeySet(fsm, data, eANI_BOOLEAN_TRUE);
                }
            }
            else 
            {
                /*
                 * Handle group key message...with group key messages,
                 * the replay counter has to change on
                 * retransmissions.
                 */
                if (!retransmit) 
                {
                    retVal = gotoStateGroupKeySet(fsm, data);
                    if( !ANI_IS_STATUS_SUCCESS( retVal ) )
                    {
                        bapSuppDisconnect( fsm->ctx );
                        return retVal;
                    }
                }
            } 
        } 
        else {
            if (fsm->integFailed) 
            {
                gotoStateKeyUpdate(fsm, arg);
            }
        }
        break;
    case GROUP_KEY_SET:
        gotoStateStaKeySet(fsm, NULL, eANI_BOOLEAN_FALSE);
        break;
    case KEY_UPDATE:
        gotoStateRekeyMsg(fsm, arg);
        break;
    default:
        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "Illegal state for SuppRsnFsm: %d",
                      fsm->currentState);
        VOS_ASSERT( 0 );
        return ANI_E_FAILED;
    }

    return ANI_OK;
}
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 int
gotoStateGroupKeySet(tSuppRsnFsm *fsm, 
                     tAniEapolKeyAvailEventData *data)
{
    int retVal;
    tAniEapolRsnKeyDesc txDesc;
    tAniEapolRsnKeyDesc *rxDesc;

    int groupKeyLen;
    
    fsm->currentState = GROUP_KEY_SET;
    
    do
    {
        rxDesc = (tAniEapolRsnKeyDesc *) data->keyDesc;
        if( NULL == rxDesc) 
        {
            retVal = ANI_E_NULL_VALUE;
            break;
        }

        if (rxDesc->keyDataLen == 0 || rxDesc->keyData == NULL) 
        {
            VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, 
                "Supp: AP sent no group key in group EAPOL-Key message!\n" );
            retVal = ANI_E_ILLEGAL_ARG;
            break;
        }

        if ( rxDesc->info.keyDescVers == ANI_EAPOL_KEY_DESC_VERS_AES ) 
        {
            groupKeyLen = rxDesc->keyDataLen - ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE;
            if( groupKeyLen <= 0 )
            {
                VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, 
                    "Supp: AP sent GTK too short\n" );
                retVal = ANI_E_ILLEGAL_ARG;
                break;
            }
        } 
        else
        {
            VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, 
                "Supp: AP sent unsupported keyDescVer %d!\n", rxDesc->info.keyDescVers );
            retVal = ANI_E_ILLEGAL_ARG;
            break;
        }

        // Always create a new EAPOL frame

        aniAsfPacketEmptyExplicit( fsm->lastEapol, 
                                  EAPOL_TX_HEADER_SIZE );
        
        vos_mem_zero( &txDesc, sizeof(txDesc) );

        // The Key Information bits...
        if (fsm->suppCtx->grpCipherType == eCSR_ENCRYPT_TYPE_AES) 
        {
            txDesc.info.keyDescVers = ANI_EAPOL_KEY_DESC_VERS_AES;
        }

        txDesc.info.unicastFlag = eANI_BOOLEAN_FALSE;
        txDesc.info.keyId = rxDesc->info.keyId;
        txDesc.info.micFlag = eANI_BOOLEAN_TRUE;
        txDesc.info.secureFlag = eANI_BOOLEAN_TRUE;
        txDesc.keyLen = RSN_80211_KEY_LEN;

        // Send back the same replayCtr that the authenticator sent
        vos_mem_copy(txDesc.replayCounter, 
               rxDesc->replayCounter, 
               sizeof(txDesc.replayCounter));

        retVal = aniEapolWriteKey(fsm->cryptHandle,
                                  fsm->lastEapol,
                                  fsm->suppCtx->authMac,
                                  fsm->suppCtx->suppMac,
                                  ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW,
                                  &txDesc,
                                  fsm->suppCtx->ptk,
                                  CSR_AES_KEY_LEN);
        if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;    

        if( !VOS_IS_STATUS_SUCCESS( bapRsnSendEapolFrame( fsm->ctx->pvosGCtx, fsm->lastEapol ) ) )
        {
            retVal = ANI_ERROR;
            VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "Supp could not send eapol. Disconnect\n" );
            break;
        }

        //FIX_RSN there is no need to set GTK retVal = setGtk(fsm->suppCtx, rxDesc->keyRecvSeqCounter);

        // This is never retransmitted
        aniAsfPacketEmptyExplicit( fsm->lastEapol, 
                                  EAPOL_TX_HEADER_SIZE );

        checkTransition(fsm, NULL); // UCT rule
    }while( 0 );

    return retVal;
}
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
gotoStateStaKeyStart(tSuppRsnFsm *fsm, 
                     tAniEapolKeyAvailEventData *data,
                     v_BOOL_t retransmit)
{
    int retVal;
    tAniEapolRsnKeyDesc txDesc;
    tAniEapolRsnKeyDesc *rxDesc;
    static v_U8_t btampRSNIE[] = {0x30, 0x14, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04, 0x01, 0x00, 
        0x00, 0x0f, 0xac, 0x04, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x02, 0x00, 0x00 };

    fsm->currentState = STA_KEY_START;

    // Create a new EAPOL frame if we don't have to retransmit
   // if (!retransmit) 
    //{

        rxDesc = data->keyDesc;
        if( NULL == rxDesc)
        {
            return ANI_E_NULL_VALUE;
        }
        aniAsfPacketEmptyExplicit( fsm->lastEapol, EAPOL_TX_HEADER_SIZE );
        retVal = derivePtk(fsm, data);
        if( !ANI_IS_STATUS_SUCCESS( retVal ) )
        {
            VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
                     "Supp derivePtk failed with code %d!\n", retVal);
            return retVal;
        }

        vos_mem_zero( &txDesc, sizeof(txDesc) );

        // The Key Information bits...
        if (fsm->suppCtx->pwCipherType == eCSR_ENCRYPT_TYPE_AES) 
        {
            txDesc.info.keyDescVers = ANI_EAPOL_KEY_DESC_VERS_AES;
        }
        txDesc.info.unicastFlag = eANI_BOOLEAN_TRUE;
        txDesc.info.micFlag = eANI_BOOLEAN_TRUE;
        txDesc.keyLen = 0; //RSN_80211_KEY_LEN;

        // Send back the same replayCtr that the authenticator sent
        vos_mem_copy(txDesc.replayCounter, 
               rxDesc->replayCounter, 
               sizeof(txDesc.replayCounter));

        vos_mem_copy(txDesc.keyNonce, fsm->sNonce, sizeof(txDesc.keyNonce));
        txDesc.keyDataLen = sizeof(btampRSNIE);//aniAsfPacketGetBytes(fsm->suppCtx->ieBp,
                                               //&txDesc.keyData);    
        txDesc.keyData = btampRSNIE;
        retVal = aniEapolWriteKey(fsm->cryptHandle,
                                  fsm->lastEapol,
                                  fsm->suppCtx->authMac,
                                  fsm->suppCtx->suppMac,
                                  ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW,
                                  &txDesc,
                                  fsm->suppCtx->ptk, 
                                  CSR_AES_KEY_LEN);
        if( !ANI_IS_STATUS_SUCCESS( retVal ) )
        {
            VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "Supp gotoStateStaKeyStart fail to write key %d\n",
                      retVal);
            return retVal;
        }
    //}
 
    if( VOS_IS_STATUS_SUCCESS( bapRsnSendEapolFrame( fsm->ctx->pvosGCtx, fsm->lastEapol ) ) )
    {
        retVal = ANI_OK;
    }
    else
    {
        retVal = ANI_ERROR;
    }

    return retVal;
}
static int
gotoStateStaKeySet(tSuppRsnFsm *fsm, 
                   tAniEapolKeyAvailEventData *data,
                   v_BOOL_t retransmit)
{
    int retVal=0;
    tAniEapolRsnKeyDesc txDesc;
    tAniEapolRsnKeyDesc *rxDesc = NULL;
    
    fsm->currentState = STA_KEY_SET;

    if (data == NULL) 
    {
        // We don't need to do anything
        return ANI_OK;
    }
    
    // Create a new EAPOL frame if we don't have to retransmit
    if (!retransmit) 
    {
        // First check the IE that the AP sent
        retVal = checkInfoElement(fsm, data);
        if (retVal != ANI_OK) 
        {
            //FIX_RSN aagSetSuppFailureAndCleanup(fsm->suppCtx);

            // FSM does not exist after this...

            return retVal;
        }

        // Create a new EAPOL frame

        rxDesc = data->keyDesc;
        if( NULL == rxDesc )
            return ANI_E_NULL_VALUE;

        aniAsfPacketEmptyExplicit(fsm->lastEapol, 
                                  EAPOL_TX_HEADER_SIZE );

        vos_mem_zero( &txDesc, sizeof(txDesc) );

        // The Key Information bits...
        if (fsm->suppCtx->pwCipherType == eCSR_ENCRYPT_TYPE_AES) 
        {
            txDesc.info.keyDescVers = ANI_EAPOL_KEY_DESC_VERS_AES;
        }

        txDesc.info.unicastFlag = eANI_BOOLEAN_TRUE;
        txDesc.info.micFlag = eANI_BOOLEAN_TRUE;
        txDesc.info.secureFlag = eANI_BOOLEAN_TRUE;
        txDesc.keyLen = 0; //RSN_80211_KEY_LEN;

        // Send back the same replayCtr that the authenticator sent
        vos_mem_copy(txDesc.replayCounter, 
               rxDesc->replayCounter, 
               sizeof(txDesc.replayCounter));

        retVal = aniEapolWriteKey(fsm->cryptHandle,
                                  fsm->lastEapol,
                                  fsm->suppCtx->authMac,
                                  fsm->suppCtx->suppMac,
                                  ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW,
                                  &txDesc,
                                  fsm->suppCtx->ptk,
                                  CSR_AES_KEY_LEN);
        if( !ANI_IS_STATUS_SUCCESS( retVal ) )
        {
            return retVal;
        }
    }
    gReadToSetKey = BAP_SET_RSN_KEY;
    if( !VOS_IS_STATUS_SUCCESS( bapRsnSendEapolFrame( fsm->ctx->pvosGCtx, fsm->lastEapol ) ) )
    {
        /* making it global to access in bapTxRx file */
#if 0
        tCsrRoamSetKey setKeyInfo;


        vos_mem_zero( &setKeyInfo, sizeof( tCsrRoamSetKey ) );
        setKeyInfo.encType = eCSR_ENCRYPT_TYPE_AES;
        setKeyInfo.keyDirection = eSIR_TX_RX;
        vos_mem_copy( setKeyInfo.peerMac, fsm->suppCtx->authMac, 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->suppCtx->ptk + (2 * CSR_AES_KEY_LEN ), CSR_AES_KEY_LEN );
        //fsm->suppCtx->ptk contains the 3 16-bytes keys. We need the last one.
        /*
          We will move the Set key to EAPOL Completion handler. We found a race condition betweem
          sending EAPOL frame and setting Key */


        if( !VOS_IS_STATUS_SUCCESS( bapSetKey( fsm->ctx->pvosGCtx, &setKeyInfo ) ) )
        {
            VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, " Supp: gotoStateStaKeySet fail to set key\n" );
            retVal = ANI_ERROR;
        }
#endif
        gReadToSetKey = BAP_RESET_RSN_KEY;
        retVal = ANI_ERROR;
    }

    return retVal;
}
static int
writeRsnKeyDesc(tAniPacket *packet, 
                tAniEapolRsnKeyDesc *rsnDesc,
                v_U8_t keyDescType)
{
    int retVal;

    do
    {
        
        
        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;

        
        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;
}
/**
 * Implements the AES Key Unwrap algorithm described in RFC 3394.
 * If (n+1) is the number of blocks in cipherText, of size
 * ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE, then the output value is (n+1)
 * blocks. The actual plaintext consists of n blocks that start at the
 * second block. Note: It is the caller's responsibility to free the
 * returned value.
 *
 * @param cipherText the cipertext data to unwrap
 * @param len the length of the ciphertext, which must be a multiple of
 * ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE.
 * @param keyEncKey the encryption key
 * @param keyEncKeyLen the length of keyEncKey
 * @param plainTextPtr is set to a newly allocated array containing
 * the result if the operation succeeds. It is the caller's
 * responsibility to free this.
 *
 * @return ANI_OK if the operation succeeds
 */
int
aniSsmAesKeyUnwrap(v_U32_t cryptHandle, tANI_U8 *cipherText, tANI_U32 len,
                   tANI_U8 *keyEncKey, tANI_U32 keyEncKeyLen,
                   tANI_U8 **plainTextPtr)
{
    int i, j;
    int retVal;

    tANI_U8 a[ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE];
    tANI_U8 *r = NULL;
    tANI_U32 n;
    tANI_U32 t;

    tANI_U8 b[ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE*2];

    n = len / ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE - 1;
    if ((len % ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE) != 0) {
        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
                   "Illegal number of input bytes to AES Key Unwrap!");
        return ANI_E_ILLEGAL_ARG;
    }

    // Allocate enough storage for 'A' as well as 'R'
    r = vos_mem_malloc((n + 1) *  ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE);
    if (r == NULL) {
        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
                   "Could not allocate space for R");
        return ANI_E_MALLOC_FAILED;
    }

    vos_mem_copy(a, cipherText, sizeof(a));
    vos_mem_copy(r + ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE,
           cipherText + ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE,
           len - ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE);

    for (j = 5; j >= 0; j--) {
        for (i = n; i >= 1; i--) {

            t = n*j + i;
            xor(a, t);
            retVal = aes_1(cryptHandle, keyEncKey, keyEncKeyLen,
                           a,
                           r + i*ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE,
                           b);
           if( !ANI_IS_STATUS_SUCCESS( retVal) ) goto error;

            vos_mem_copy(a, b, ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE);
            vos_mem_copy(r + i*ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE,
                   b + sizeof(b) - ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE,
                   ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE);
        }
    }

    if (vos_mem_compare2(a, gAniSsmAesKeyWrapIv, ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE) != 0) {
        retVal = ANI_E_MIC_FAILED;
        goto error;
    }

    *plainTextPtr = r;

    return ANI_OK;

 error:
    if (r != NULL)
        vos_mem_free(r);

    return retVal;
}
示例#22
0
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;
}
示例#23
0
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;
}
static int
gotoStatePtkInitNegoTx(tAuthRsnFsm *fsm)
{
    tAniEapolRsnKeyDesc txDesc;
    v_BOOL_t retransmit = eANI_BOOLEAN_FALSE;
    v_U8_t *rsnWpaIe = NULL;
    int rsnWpaIeLen;
    static tAniPacket *keyData;
    // 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;
}
示例#25
0
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
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]; 

    
    
    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;
        }
        
        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;

    
    vos_mem_zero( micPos, VOS_DIGEST_MD5_SIZE);

    
    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) 
    {
        
        
        vos_mem_copy(micPos, result, VOS_DIGEST_MD5_SIZE);
    }

    return retVal;
}
示例#27
0
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 = NULL;
    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) || (NULL == pFrame) ) 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;
        if (uPktLen <= 0){
           VOS_ASSERT(0);
           retVal = ANI_ERROR;
           break;
        }

        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;
}
示例#28
0
/**
 * 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;
}