/** * suppRsnFsmFree * * FUNCTION * Frees a previously allocated RSN Key FSM in a BP context. If the * RSN Key FSM is not yet allocated, then this is an error. * * @param ctx the BP context whose FSM instance is to be freed * * @return ANI_OK if the operation succeeds */ int suppRsnFsmFree(tBtampContext *ctx) { tSuppRsnFsm *fsm; fsm = &ctx->uFsm.suppFsm; if( fsm->cryptHandle ) { vos_crypto_deinit( fsm->cryptHandle ); } bapRsnClearTxRxCallbacks(); if (fsm->lastEapol) aniAsfPacketFree(fsm->lastEapol); if( fsm->suppCtx ) { if ( fsm->suppCtx->pmk ) { aniAsfPacketFree(fsm->suppCtx->pmk); } vos_mem_free( fsm->suppCtx ); } // Finally, clear everything out vos_mem_zero( fsm, sizeof(tSuppRsnFsm)); return ANI_OK; }
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 ); }
/** * aniAsfPacketDuplicate * * Duplicates a given packet exactly. That is, the contents, the size * of the packet, and the positions of the pointers are maintained in * the new copy. * * @param newPacketPtr is set to a newly allocated packet that is a * duplicate of oldPacket * @param oldPacket the original packet that should be duplicated * * @return ANI_OK if the operation succeeds; ANI_E_NULL if oldPacket * is NULL; */ int aniAsfPacketDuplicate(tAniPacket **newPacketPtr, tAniPacket *oldPacket) { int retVal; int recordPos; tAniPacket *packet = NULL; if (oldPacket == NULL) return ANI_E_NULL_VALUE; retVal = aniAsfPacketAllocateExplicit(&packet, oldPacket->size, oldPacket->head - oldPacket->buf); if (retVal != ANI_OK) return retVal; retVal = aniAsfPacketAppendBuffer(packet, oldPacket->head, oldPacket->len); if (retVal != ANI_OK) { VOS_ASSERT( 0 ); aniAsfPacketFree(packet); return ANI_E_FAILED; } if (oldPacket->recordHeader != NULL) { recordPos = oldPacket->recordHeader - oldPacket->buf; packet->recordHeader = packet->buf + recordPos; } *newPacketPtr = packet; return ANI_OK; }
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; if( fIsAuth ) { tAuthRsnFsm *fsm = (tAuthRsnFsm *)pvFsm; authEapolHandler( fsm, packet, dstMac, srcMac, type ); } else { tSuppRsnFsm *fsm = (tSuppRsnFsm *)pvFsm; suppEapolHandler(fsm, packet, dstMac, srcMac, type); } } 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 ); }
/** * authRsnFsmFree * * FUNCTION * Frees a previously allocated RSN Key FSM in a STA context. If the * RSN Key FSM is not yet allocated, then this is an error. * * @param ctx the STA context whose FSM instance is to be freed * * @return ANI_OK if the operation succeeds */ int authRsnFsmFree(tBtampContext *ctx) { tAuthRsnFsm *fsm = &ctx->uFsm.authFsm; VOS_ASSERT(fsm); if( fsm->cryptHandle) { vos_crypto_deinit( fsm->cryptHandle ); } bapRsnClearTxRxCallbacks(); if ( fsm->staCtx ) { fsm->staCtx->authRsnFsm = NULL; } if ( VOS_TIMER_STATE_UNUSED != fsm->msg2Timer.state ) vos_timer_destroy( &fsm->msg2Timer ); if ( VOS_TIMER_STATE_UNUSED != fsm->msg4Timer.state ) vos_timer_destroy( &fsm->msg4Timer ); if (fsm->lastEapol) { aniAsfPacketFree(fsm->lastEapol); fsm->lastEapol = NULL; } if( fsm->staCtx ) { if( fsm->staCtx->pmk ) { aniAsfPacketFree( fsm->staCtx->pmk ); fsm->staCtx->pmk = NULL; } vos_mem_free(fsm->staCtx); fsm->staCtx = NULL; } vos_mem_zero( fsm, sizeof(tAuthRsnFsm) ); return ANI_OK; }
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; }
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; }
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; }