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