/** * 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; }
/** * aniAsfPacketAllocate * * FUNCTION: * Create a packet of size 2*ANI_DEFAULT_PACKET_SIZE and positions the * head of the packet in the center. The allocated storage can be free * with a call to aniAsfPacketFree. * * LOGIC: * Allocates storage for tAniPacket and its internal raw data * buffer. Positions the head and tail pointers in the middle of the * raw data buffer. * * @param packetPtr pointer that will be set to newly allocated * tAniPacket if the operation succeeds. * * @return ANI_OK if the operation succeeds; ANI_E_MALLOC_FAILED if * memory could not be allocated. * @see aniAsfPacketFree */ int aniAsfPacketAllocate(tAniPacket **packetPtr) { return aniAsfPacketAllocateExplicit(packetPtr, ANI_INTERNAL_DEFAULT_PACKET_SIZE, ANI_INTERNAL_DEFAULT_PACKET_SIZE/2); }
/** * suppRsnFsmCreate * * FUNCTION * Allocates and initializes the state of an RSN key FSM instance for * the given BP context. * * @parm ctx the BP context whose instance is being created * @param pskBased pass in eANI_BOOLEAN_TRUE is this BP is to be * authenticated based on a pre-shared key as opposed to EAP. * * @return ANI_OK if the operation succeeds */ int suppRsnFsmCreate(tBtampContext *ctx) { int retVal = ANI_OK; tSuppRsnFsm *fsm = &ctx->uFsm.suppFsm; // First, clear everything out vos_mem_zero( fsm, sizeof(tSuppRsnFsm)); if( !VOS_IS_STATUS_SUCCESS( bapRsnRegisterTxRxCallbacks( suppRsnTxCompleteHandler, suppRsnRxFrameHandler ) ) ) { return ANI_ERROR; } if( !VOS_IS_STATUS_SUCCESS( bapRsnRegisterRxCallback( ctx->pvosGCtx ) ) ) { return ANI_ERROR; } // Allocate the supplicant context fsm->suppCtx = (tSuppContext *)vos_mem_malloc( sizeof(tSuppContext) ); if (fsm->suppCtx == NULL) { retVal = ANI_E_MALLOC_FAILED; VOS_ASSERT( 0 ); goto error; } // Clear out the supplicant context vos_mem_zero( fsm->suppCtx, sizeof(tSuppContext)); fsm->ctx = ctx; //Only support CCMP fsm->suppCtx->pwCipherType = eCSR_ENCRYPT_TYPE_AES; retVal = aniAsfPacketAllocateExplicit(&fsm->lastEapol, RSN_MAX_PACKET_SIZE, EAPOL_TX_HEADER_SIZE); if (retVal != ANI_OK) { VOS_ASSERT( 0 ); goto error; } aniAsfPacketAllocate(&fsm->suppCtx->pmk); if (fsm->suppCtx->pmk == NULL) { retVal = ANI_E_MALLOC_FAILED; VOS_ASSERT( 0 ); goto error; } fsm->suppCtx->ieAp = NULL; fsm->cryptHandle = 0; if( !VOS_IS_STATUS_SUCCESS( vos_crypto_init( &fsm->cryptHandle ) ) ) { retVal = ANI_E_FAILED; VOS_ASSERT( 0 ); } fsm->currentState = INITIALIZE; gotoStateInit(fsm); suppRsnFsmProcessEvent( fsm, RSN_FSM_AUTH_START, NULL ); return ANI_OK; error: suppRsnFsmFree( ctx ); return retVal; }
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; }
/** * authRsnFsmCreate * * FUNCTION * Allocates and initializes the state of an RSN key FSM instance for * the given STA context. * * @parm staCtx the STA context whose instance is being created * @param pskBased pass in eANI_BOOLEAN_TRUE is this STA is to be * authenticated based on a pre-shared key as opposed to EAP. * * @return ANI_OK if the operation succeeds */ int authRsnFsmCreate(tBtampContext *ctx) { int retVal = ANI_OK; tAuthRsnFsm *fsm = &ctx->uFsm.authFsm; // First, clear everything out vos_mem_zero( fsm, sizeof(tAuthRsnFsm)); if( !VOS_IS_STATUS_SUCCESS( bapRsnRegisterTxRxCallbacks( authRsnTxCompleteHandler, authRsnRxFrameHandler ) ) ) { return ANI_ERROR; } if( !VOS_IS_STATUS_SUCCESS( bapRsnRegisterRxCallback( ctx->pvosGCtx ) ) ) { return ANI_ERROR; } // Allocate the station context fsm->staCtx = (tStaContext *)vos_mem_malloc( sizeof(tStaContext) ); if (fsm->staCtx == NULL) { retVal = ANI_E_MALLOC_FAILED; VOS_ASSERT( 0 ); goto error; } // Clear out the station context vos_mem_zero( fsm->staCtx, sizeof(tStaContext) ); fsm->ctx = ctx; fsm->staCtx->authRsnFsm = fsm; //Only support CCMP fsm->staCtx->pwCipherType = eCSR_ENCRYPT_TYPE_AES; if( !VOS_IS_STATUS_SUCCESS( vos_timer_init( &fsm->msg2Timer, VOS_TIMER_TYPE_SW, msg2TimerCallback, fsm ) ) ) { retVal = ANI_E_MALLOC_FAILED; VOS_ASSERT( 0 ); goto error; } if( !VOS_IS_STATUS_SUCCESS( vos_timer_init( &fsm->msg4Timer, VOS_TIMER_TYPE_SW, msg4TimerCallback, fsm ) ) ) { retVal = ANI_E_MALLOC_FAILED; VOS_ASSERT( 0 ); goto error; } retVal = aniAsfPacketAllocateExplicit(&fsm->lastEapol, RSN_MAX_PACKET_SIZE, EAPOL_TX_HEADER_SIZE ); if (retVal != ANI_OK) { VOS_ASSERT( 0 ); goto error; } aniAsfPacketAllocate(&fsm->staCtx->pmk); if (fsm->staCtx->pmk == NULL) { retVal = ANI_E_MALLOC_FAILED; VOS_ASSERT( 0 ); goto error; } aniAsfPacketAllocateExplicit(&fsm->staCtx->ieSta, RSN_IE_MAX_PACKET_SIZE, RSN_IE_HEADER_SIZE ); if (fsm->staCtx->ieSta == NULL) { retVal = ANI_E_MALLOC_FAILED; VOS_ASSERT( 0 ); goto error; } fsm->cryptHandle = 0; if( !VOS_IS_STATUS_SUCCESS( vos_crypto_init( &fsm->cryptHandle ) ) ) { retVal = ANI_E_FAILED; VOS_ASSERT( 0 ); goto error; } fsm->currentState = INITIALIZE; gotoStateInit(fsm); //We can call this function here because it is connected at this time authRsnFsmProcessEvent( fsm, RSN_FSM_AUTH_START, NULL ); return ANI_OK; error: authRsnFsmFree(ctx); return retVal; }