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