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