blob: fcbc6e494a2b648d9494a93b95fb676286ada36a [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Kiet Lam842dad02014-02-18 18:44:02 -08002 * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080020 */
Kiet Lam842dad02014-02-18 18:44:02 -080021
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080022/*
Kiet Lam842dad02014-02-18 18:44:02 -080023 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/*
Jeff Johnson295189b2012-06-20 16:38:30 -070029 * $File: //depot/software/projects/feature_branches/gen5_phase1/os/linux/classic/ap/apps/ssm/auth8021x/ani8021xAuthRsnFsm.c $
30 *
31 * Contains definitions for the RSN EAPOL-Key FSM on the
32 * authenticator side. This is based on 802.11i.
33 *
34 * Author: Mayank D. Upadhyay
35 * Date: 19-December-2002
36 * History:-
37 * Date Modified by Modification Information
38 * ------------------------------------------------------
39 *
40 */
41#include "vos_types.h"
42#include "bapRsnSsmServices.h"
43#include "bapRsnSsmEapol.h"
44#include "bapRsnErrors.h"
45#include "bapInternal.h"
46#include "bapRsn8021xFsm.h"
47#include "bapRsn8021xAuthFsm.h"
48#include "vos_utils.h"
49#include "vos_memory.h"
50#include "vos_timer.h"
51#include "bapRsnTxRx.h"
52#include "bapRsnSsmAesKeyWrap.h"
53#include "btampFsm.h"
54
55// The different states that this FSM transitions through
56#define DISCONNECT 0
57#define DISCONNECTED 1
58#define INITIALIZE 2
59#define AUTHENTICATION 3
60#define AUTHENTICATION_2 4
61#define GET_PSK 5
62#define GET_EAP_KEY 6
63#define PTK_START 7
64#define PTK_INIT_NEGO 8
65#define PTK_INIT_NEGO_TX 9
66#define PTK_INIT_DONE 10
67#define UPDATE_KEYS_REQ 11
68#define INTEG_FAILURE 12
69#define KEY_UPDATE 13
70#define NUM_STATES (KEY_UPDATE + 1)
71
72
73
74static tAuthRsnFsmConsts authConsts = { 2000, 3 }; //timeout, retry limit
75static v_U8_t aniSsmIeRsnOui[] = ANI_SSM_IE_RSN_OUI;
76
77
78/**************************************
79 * Static functions in this module
80 **************************************/
81
82static
83int zeroOutPtk(tAuthRsnFsm *fsm);
84static
85int stopAllTimers(tAuthRsnFsm *fsm);
86
87static
88int checkMic(tAuthRsnFsm *fsm,
89 tAniEapolKeyAvailEventData *data);
90
91static
92int checkLocalReplayCounter(tAuthRsnFsm *fsm,
93 tAniEapolKeyAvailEventData *data);
94static
95int checkPeerReplayCounter(tAuthRsnFsm *fsm,
96 tAniEapolKeyAvailEventData *data);
97
98static int checkInfoElement(tAuthRsnFsm *fsm,
99 tAniEapolKeyAvailEventData *data);
100
101static
102int derivePtk(tAuthRsnFsm *fsm,
103 tAniEapolKeyAvailEventData *data);
104
105
106static int checkTransition(tAuthRsnFsm *fsm, void *arg);
107
108static int
109gotoStateInit(tAuthRsnFsm *fsm);
110
111static void msg2TimerCallback( void * );
112static void msg4TimerCallback( void * );
113
114static int authRsnRxFrameHandler( v_PVOID_t pvosGCtx, vos_pkt_t *pPacket );
115static int authRsnTxCompleteHandler( v_PVOID_t pvosGCtx, vos_pkt_t *pPacket, VOS_STATUS retStatus );
116
117/********************************
118 * Functions Forward Declarations
119 ********************************/
120
121int authRsnAuthStartEventHandler( tAuthRsnFsm *fsm );
122int authRsnAuthDisconEventHandler( tAuthRsnFsm *fsm );
123
124/*************************
125 * The exported functions
126 *************************/
127
128/**
129 * authRsnFsmInit
130 *
131 * FUNCTION:
132 * Initializes the constants and the callbacks needed by this FSM
133 * module.
134 *
135 * @param consts the various constant values needed by this FSM
136 * @param cb callbacks to the various procedures needed by this FSM
137 *
138 * @return ANI_OK if the operation succeeds
139 */
140int
141authRsnFsmInit(tAuthRsnFsmConsts *constsIn)
142{
143 // TODO: Read the constants in from config
144 // authConsts = *constsIn;
145 authConsts.timeoutPeriod = 2000; //ms
146 authConsts.maxTries = 3;
147
148 return ANI_OK;
149}
150
151/**
152 * authRsnFsmCreate
153 *
154 * FUNCTION
155 * Allocates and initializes the state of an RSN key FSM instance for
156 * the given STA context.
157 *
158 * @parm staCtx the STA context whose instance is being created
159 * @param pskBased pass in eANI_BOOLEAN_TRUE is this STA is to be
160 * authenticated based on a pre-shared key as opposed to EAP.
161 *
162 * @return ANI_OK if the operation succeeds
163 */
164int
165authRsnFsmCreate(tBtampContext *ctx)
166{
167 int retVal = ANI_OK;
168 tAuthRsnFsm *fsm = &ctx->uFsm.authFsm;
169
170 // First, clear everything out
171 vos_mem_zero( fsm, sizeof(tAuthRsnFsm));
172
173 if( !VOS_IS_STATUS_SUCCESS( bapRsnRegisterTxRxCallbacks( authRsnTxCompleteHandler,
174 authRsnRxFrameHandler ) ) )
175 {
176 return ANI_ERROR;
177 }
178
179 if( !VOS_IS_STATUS_SUCCESS( bapRsnRegisterRxCallback( ctx->pvosGCtx ) ) )
180 {
181 return ANI_ERROR;
182 }
183
184 // Allocate the station context
185 fsm->staCtx = (tStaContext *)vos_mem_malloc( sizeof(tStaContext) );
186 if (fsm->staCtx == NULL)
187 {
188 retVal = ANI_E_MALLOC_FAILED;
189 VOS_ASSERT( 0 );
190 goto error;
191 }
192 // Clear out the station context
193 vos_mem_zero( fsm->staCtx, sizeof(tStaContext) );
194
195 fsm->ctx = ctx;
196 fsm->staCtx->authRsnFsm = fsm;
197 //Only support CCMP
198 fsm->staCtx->pwCipherType = eCSR_ENCRYPT_TYPE_AES;
199
200 if( !VOS_IS_STATUS_SUCCESS( vos_timer_init( &fsm->msg2Timer, VOS_TIMER_TYPE_SW, msg2TimerCallback, fsm ) ) )
201 {
202 retVal = ANI_E_MALLOC_FAILED;
203 VOS_ASSERT( 0 );
204 goto error;
205 }
206
207 if( !VOS_IS_STATUS_SUCCESS( vos_timer_init( &fsm->msg4Timer, VOS_TIMER_TYPE_SW, msg4TimerCallback, fsm ) ) )
208 {
209 retVal = ANI_E_MALLOC_FAILED;
210 VOS_ASSERT( 0 );
211 goto error;
212 }
213
214 retVal = aniAsfPacketAllocateExplicit(&fsm->lastEapol,
215 RSN_MAX_PACKET_SIZE,
216 EAPOL_TX_HEADER_SIZE );
217 if (retVal != ANI_OK)
218 {
219 VOS_ASSERT( 0 );
220 goto error;
221 }
222
223 aniAsfPacketAllocate(&fsm->staCtx->pmk);
224 if (fsm->staCtx->pmk == NULL)
225 {
226 retVal = ANI_E_MALLOC_FAILED;
227 VOS_ASSERT( 0 );
228 goto error;
229 }
230
231 aniAsfPacketAllocateExplicit(&fsm->staCtx->ieSta,
232 RSN_IE_MAX_PACKET_SIZE,
233 RSN_IE_HEADER_SIZE );
234 if (fsm->staCtx->ieSta == NULL)
235 {
236 retVal = ANI_E_MALLOC_FAILED;
237 VOS_ASSERT( 0 );
238 goto error;
239 }
240
241 fsm->cryptHandle = 0;
242 if( !VOS_IS_STATUS_SUCCESS( vos_crypto_init( &fsm->cryptHandle ) ) )
243 {
244 retVal = ANI_E_FAILED;
245 VOS_ASSERT( 0 );
246 goto error;
247 }
248
249 fsm->currentState = INITIALIZE;
250 gotoStateInit(fsm);
251
252 //We can call this function here because it is connected at this time
253 authRsnFsmProcessEvent( fsm, RSN_FSM_AUTH_START, NULL );
254
255 return ANI_OK;
256
257 error:
258 authRsnFsmFree(ctx);
259
260 return retVal;
261
262}
263
264/**
265 * authRsnFsmFree
266 *
267 * FUNCTION
268 * Frees a previously allocated RSN Key FSM in a STA context. If the
269 * RSN Key FSM is not yet allocated, then this is an error.
270 *
271 * @param ctx the STA context whose FSM instance is to be freed
272 *
273 * @return ANI_OK if the operation succeeds
274 */
275int
276authRsnFsmFree(tBtampContext *ctx)
277{
278 tAuthRsnFsm *fsm = &ctx->uFsm.authFsm;
279
280 VOS_ASSERT(fsm);
281
282 if( fsm->cryptHandle)
283 {
284 vos_crypto_deinit( fsm->cryptHandle );
285 }
286
287 bapRsnClearTxRxCallbacks();
288
289 if ( fsm->staCtx )
290 {
291 fsm->staCtx->authRsnFsm = NULL;
292 }
293
294 if ( VOS_TIMER_STATE_UNUSED != fsm->msg2Timer.state ) vos_timer_destroy( &fsm->msg2Timer );
295 if ( VOS_TIMER_STATE_UNUSED != fsm->msg4Timer.state ) vos_timer_destroy( &fsm->msg4Timer );
296
297 if (fsm->lastEapol)
298 {
299 aniAsfPacketFree(fsm->lastEapol);
300 fsm->lastEapol = NULL;
301 }
302
303 if( fsm->staCtx )
304 {
305 if( fsm->staCtx->pmk )
306 {
307 aniAsfPacketFree( fsm->staCtx->pmk );
308 fsm->staCtx->pmk = NULL;
309 }
310 vos_mem_free(fsm->staCtx);
311 fsm->staCtx = NULL;
312 }
313
314 vos_mem_zero( fsm, sizeof(tAuthRsnFsm) );
315
316 return ANI_OK;
317}
318
319/**
320 * authRsnFsmProcessEvent
321 *
322 * FUNCTION
323 * Passes an event to the RSN key FSM instance for immediate processing.
324 *
325 * @param fsm the RSN Key FSM instance
326 * @param eventId the AAG event to process
327 * @param arg an optional argument for this event
328 *
329 * @return ANI_OK if the operation succeeds
330 */
331int
332authRsnFsmProcessEvent(tAuthRsnFsm *fsm, tRsnFsmEvent eventId, void *arg)
333{
334 VOS_ASSERT(fsm);
335
336 switch (eventId) {
337 case RSN_FSM_TIMER_EXPIRED:
338 // Proceed straight to checkTransition
339 break;
340 case RSN_FSM_AUTH_START:
341 fsm->authReq = eANI_BOOLEAN_TRUE;
342 authRsnAuthStartEventHandler(fsm);
343 break;
344 case RSN_FSM_EAPOL_FRAME_AVAILABLE:
345 fsm->eapolAvail = eANI_BOOLEAN_TRUE;
346 break;
347 case RSN_FSM_DISCONNECT:
348 fsm->disconnect = eANI_BOOLEAN_TRUE;
349 authRsnAuthDisconEventHandler(fsm);
350 break;
351 case RSN_FSM_INTEG_FAILED:
352 fsm->integFailed = eANI_BOOLEAN_TRUE;
353 break;
354 default:
355 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
356 "Unknown event for Auth RSN Key Fsm: %d\n", eventId);
357 VOS_ASSERT( 0 );
358 return ANI_E_ILLEGAL_ARG;
359 break;
360 }
361
362 checkTransition(fsm, arg);
363
Madan Mohan Koyyalamudi4e31b132012-11-02 13:13:52 -0700364 return ANI_OK;
Jeff Johnson295189b2012-06-20 16:38:30 -0700365}
366
367
368int
369authRsnAuthStartEventHandler(tAuthRsnFsm *fsm)
370{
371 static v_U8_t btampStaRSNIE[] = {0x30, 0x14, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04, 0x01, 0x00,
372 0x00, 0x0f, 0xac, 0x04, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x02, 0x00, 0x00 };
373 // Copy required info
374 vos_mem_copy( &fsm->staCtx->authMac, fsm->ctx->self_mac_addr, 6);
375 vos_mem_copy( &fsm->staCtx->suppMac, fsm->ctx->peer_mac_addr, 6);
376 aniAsfPacketAppendBuffer( fsm->staCtx->pmk, fsm->ctx->key_material, fsm->ctx->key_length);
377
378 aniAsfPacketAppendBuffer( fsm->staCtx->ieSta, btampStaRSNIE, sizeof(btampStaRSNIE));
379 return ANI_OK;
380}
381
382int
383authRsnAuthDisconEventHandler(tAuthRsnFsm *fsm)
384{
385 // Free Stactx .?
386 return ANI_OK;
387}
388
389/***********************
390 * The static functions
391 ***********************/
392
393static int
394gotoStateInit(tAuthRsnFsm *fsm)
395{
396 fsm->currentState = INITIALIZE;
397
398 // TODO: Move this to a global position which applies to WEP as
399 // well
400 //initGlobalKeys = eANI_BOOLEAN_FALSE;
401
402 fsm->authReq = eANI_BOOLEAN_FALSE;
403 fsm->eapolAvail = eANI_BOOLEAN_FALSE;
404 fsm->disconnect = eANI_BOOLEAN_FALSE;
405 fsm->integFailed = eANI_BOOLEAN_FALSE;
406
407 fsm->numTries = 0;
408
409 // Create two replay counter's..one for our requests, and another
410 // for STA's requests. Initialize the first one randomly.
411 aniSsmReplayCtrCreate(fsm->cryptHandle, &fsm->staCtx->localReplayCtr,
412 ANI_EAPOL_KEY_RSN_RSC_SIZE, 0);
413 aniSsmReplayCtrCreate(fsm->cryptHandle, &fsm->staCtx->peerReplayCtr,
414 ANI_EAPOL_KEY_RSN_RSC_SIZE, 0);
415
416 return ANI_OK;
417}
418
419static int
420gotoStateAuthentication(tAuthRsnFsm *fsm)
421{
422 fsm->currentState = AUTHENTICATION;
423
424 zeroOutPtk(fsm);
425 fsm->authReq = eANI_BOOLEAN_FALSE;
426
427 checkTransition(fsm, NULL); // UCT rule
428
429 return ANI_OK;
430}
431
432static int
433gotoStateAuthentication2(tAuthRsnFsm *fsm)
434{
435 fsm->currentState = AUTHENTICATION_2;
436
437 if( !VOS_IS_STATUS_SUCCESS( vos_rand_get_bytes( fsm->cryptHandle, fsm->aNonce, ANI_EAPOL_KEY_RSN_NONCE_SIZE ) ) )
438 {
439 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
440 "gotoStateAuthentication2 fail to get random number. Disconnect\n" );
441 bapAuthDisconnect( fsm->ctx );
442 return ANI_ERROR;
443 }
444 fsm->numTries = 0;
445
446 checkTransition(fsm, NULL); // UCT rule
447
448 return ANI_OK;
449}
450
451
452static int
453gotoStateGetPsk(tAuthRsnFsm *fsm)
454{
455 //This is simply a transaction because we already have the PMK. We always do.
456 fsm->currentState = GET_PSK;
457
458 fsm->numTries = 0;
459
460 checkTransition(fsm, NULL);
461
462 return ANI_OK;
463}
464
465static int
466gotoStatePtkStart(tAuthRsnFsm *fsm)
467{
468 tAniEapolRsnKeyDesc txDesc;
469 int retVal;
470
471 fsm->msg2TimeOut = VOS_FALSE;
472 fsm->currentState = PTK_START;
473
474 // Create a new packet if we don't have one to retransmit
475 //if (aniAsfPacketGetLen(fsm->lastEapol) == 0)
476#if 0
477 if( fsm->lastEapol )
478 {
479 aniAsfPacketFree( fsm->lastEapol );
480 fsm->lastEapol = NULL;
481
482 retVal = aniAsfPacketAllocateExplicit(&fsm->lastEapol,
483 RSN_MAX_PACKET_SIZE,
484 EAPOL_TX_HEADER_SIZE );
485#endif
486 aniAsfPacketEmptyExplicit(fsm->lastEapol,
487 EAPOL_TX_HEADER_SIZE);
488 //}
489 // if (1)
490 //{
491
492 vos_mem_zero( &txDesc, sizeof(txDesc) );
493
494 // The Key Information bits...
495 if (fsm->staCtx->pwCipherType == eCSR_ENCRYPT_TYPE_AES)
496 {
497 txDesc.info.keyDescVers = ANI_EAPOL_KEY_DESC_VERS_AES;
498 }
499 else {
500 return ANI_E_ILLEGAL_ARG;
501 }
502 txDesc.info.unicastFlag = eANI_BOOLEAN_TRUE;
503 txDesc.info.ackFlag = eANI_BOOLEAN_TRUE;
504
505 // The other fields...
506 txDesc.keyLen = aagGetKeyMaterialLen(fsm->staCtx->pwCipherType);
507 aniSsmReplayCtrNext(fsm->staCtx->localReplayCtr, txDesc.replayCounter);
508 vos_mem_copy(txDesc.keyNonce, fsm->aNonce, sizeof(txDesc.keyNonce));
509
510 retVal = aniEapolWriteKey(fsm->cryptHandle,
511 fsm->lastEapol,
512 fsm->staCtx->suppMac,
513 fsm->staCtx->authMac,
514 ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW,
515 &txDesc,
516 NULL, 0);
517 if( !ANI_IS_STATUS_SUCCESS( retVal ) )
518 {
519 return retVal;
520 }
521#if 0
522 }
523 else {
524 retransmit = eANI_BOOLEAN_TRUE;
525 }
526#endif
527
528 if( VOS_IS_STATUS_SUCCESS( bapRsnSendEapolFrame( fsm->ctx->pvosGCtx, fsm->lastEapol ) ) )
529 {
530 retVal = ANI_OK;
531 }
532 else
533 {
534 //we fail to send the eapol frame disconnect
535 bapAuthDisconnect( fsm->ctx );
536 retVal = ANI_ERROR;
537 }
538
539 return retVal;
540}
541
542static int
543gotoStatePtkInitNego(tAuthRsnFsm *fsm, void *arg)
544{
545 fsm->currentState = PTK_INIT_NEGO;
546
547 // Replay counter will be automatically updated when we create a
548 // new packet
549
550 fsm->numTries = 0;
551 aniAsfPacketEmptyExplicit(fsm->lastEapol,
552 EAPOL_TX_HEADER_SIZE);
553
554 checkTransition(fsm, arg);
555
556 return ANI_OK;
557}
558
559// Use this only with trusted IE like the one we generated locally
560static int
561getRsnIeFromAdvertizedIes(tAuthRsnFsm *fsm, v_U8_t **rsnIe)
562{
563 int retVal = ANI_E_ILLEGAL_ARG;
564 v_U8_t *ptr = fsm->advertizedRsnIe;
565
566 if (*ptr == ANI_SSM_IE_RSN_ELEM_ID)
567 {
568 retVal = *(ptr + 1) + 2; // The L field from the TLV + 2B TL
569 *rsnIe = ptr;
570 }
571
572 return retVal;
573}
574
575// Use this only with trusted IE like the one we generated locally
576static void
577addPad(
578 v_U8_t *dataBytes,
579 int dataLen,
580 int padLen)
581{
582 int i;
583
584 // The first byte of padding is 0xdd. The rest are 0x00's
585 // See 802.11i section 8.5.2 subsection "Key Data Encapsulation"
586
587 for ( i=dataLen ; i < dataLen+padLen; i++)
588 {
589 if ( i == dataLen )
590 {
591 dataBytes[i] = 0xdd;
592 }
593 else {
594 dataBytes[i] = 0x00;
595 }
596 }
597
598 return;
599}
600
601/**
602 * aagAppendGroupKeyForRsn
603 *
604 * Appends the group key to the packet in the RSN key encapulation format.
605 *
606 * @param packet - the packet to append to
607 * @param radioId - the radio whose group key needs to be appended
608 *
609 * @return ANI_OK if the operation succeeds
610 */
611#define STATIC_WEP_KEY_LEN 16
612#define GROUP_KEY_ID 0
613#define ANI_SSM_IE_RSN_KEY_DATA_ENCAPS_ID 0xDD
614#define ANI_SSM_IE_RSN_GROUP_KEY_DATA_ENCAPS_ID 1
615
616int
617aagAppendGroupKeyForRsn(tAniPacket *packet)
618{
619#if 0
620 tAniPacket *groupKey = NULL;
621#else
622 tANI_U8 groupKey[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
623 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15};
624#endif
625 tANI_U8 *groupKeyBytes = NULL;
626 tANI_U8 *lenPtr = NULL;
627 tANI_U8 *endPtr = NULL;
628 int groupKeyLen;
629 int retVal;
630
631#if 0
632 groupKey = AAG_GROUP_KEY(radioId);
633 if (groupKey == NULL) {
634 ANI_AAG_LOG_E("Group key is not yet set on radio %d, id %d!",
635 radioId, AAG_GROUP_KEY_ID(radioId));
636 assert(0 && "Group key is still NULL!");
637 return ANI_E_FAILED;
638 }
639
640 groupKeyLen = aniAsfPacketGetBytes(groupKey, &groupKeyBytes);
641 CHECK_NO_ERROR(groupKeyLen);
642
643 if (aagConfig.logLevel >= LOG_INFO) {
644 ANI_AAG_LOG_D("Will encapsulate group key bytes %s",
645 aniAsfHexStr(groupKeyBytes, groupKeyLen));
646 }
647#else
648 groupKeyBytes = groupKey;
649
650 groupKeyLen = STATIC_WEP_KEY_LEN;
651#endif
652
653 /*
654 * Add the key data encapsulation needed for RSN/WPA2
655 */
656
657 // The IE ID
658 retVal = aniAsfPacketAppend8(packet, ANI_SSM_IE_RSN_KEY_DATA_ENCAPS_ID);
659 //CHECK_NO_ERROR(retVal);
660
661 // Obtain the position for the length
662 aniAsfPacketGetBytesFromTail(packet, &lenPtr);
663
664 // Write out a dummy length - we'll fill this in later. It will be
665 // 6 bytes more than the length of the GTK
666 retVal = aniAsfPacketAppend8(packet, 0);
667 //CHECK_NO_ERROR(retVal);
668
669 // Copy the RSN OUI
670 retVal = aniAsfPacketAppendBuffer(packet, aniSsmIeRsnOui, sizeof(aniSsmIeRsnOui));
671 //CHECK_NO_ERROR(retVal);
672
673 // Indicate that the key type is group key
674 retVal = aniAsfPacketAppend8(packet, ANI_SSM_IE_RSN_GROUP_KEY_DATA_ENCAPS_ID);
675 //CHECK_NO_ERROR(retVal);
676
677 // Copy the key-id to the first two bits of the next byte
678 // Copy the Tx bit the third bit of the same byte
679 // (Here, I assume the Group Key is to be used for both STA Tx and Rx)
680 retVal = aniAsfPacketAppend8(
681 packet,
682 GROUP_KEY_ID );
683 //AAG_GROUP_KEY_ID(radioId) );
684 //CHECK_NO_ERROR(retVal);
685
686 retVal = aniAsfPacketMoveRight(packet, 1); // Reserved bits (1 byte)
687 //CHECK_NO_ERROR(retVal);
688
689 // Copy the real key bytes
690 retVal = aniAsfPacketAppendBuffer(packet, groupKeyBytes, groupKeyLen);
691 //CHECK_NO_ERROR(retVal);
692
693 // Calculate and enter the length of the entire encoding
694 aniAsfPacketGetBytesFromTail(packet, &endPtr);
695 *lenPtr = endPtr - (lenPtr + 1) ; // subtract one to avoid tail
696
697 return retVal;
698}
699
700static int
701gotoStatePtkInitNegoTx(tAuthRsnFsm *fsm)
702{
703 tAniEapolRsnKeyDesc txDesc;
704 v_BOOL_t retransmit = eANI_BOOLEAN_FALSE;
705 v_U8_t *rsnWpaIe = NULL;
706 int rsnWpaIeLen;
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700707 static tAniPacket *keyData;
Jeff Johnson295189b2012-06-20 16:38:30 -0700708 // The longest length...the extra 8 bytes account for RSN key data
709 // encapsulation
710 v_U8_t paddedGroupKeyEncaps[1024];
711 int padLen = 0;
712 v_U8_t *groupKeyBytes;
713 int groupKeyLen;
714 v_U8_t *wrappedKey = NULL;
715 // Variables used for RC4 GTK wrap
716 //v_U8_t keyIv[ANI_EAPOL_KEY_RSN_IV_SIZE];
717 //v_U32_t keyIvLsb;
718 int retVal = 0;
719
720 //invalidate this
721 fsm->msg4TimeOut = VOS_FALSE;
722 fsm->currentState = PTK_INIT_NEGO_TX ;
723
724 if (keyData == NULL)
725 {
726 // Allocate the packet the first time around that you enter
727 retVal = aniAsfPacketAllocateExplicit(&keyData, 1024, 10);
728 if( !ANI_IS_STATUS_SUCCESS( retVal ) )
729 {
730 return retVal;
731 }
732 }
733 else {
734 // Just empty out the packet
735 aniAsfPacketEmptyExplicit(keyData, 10);
736 }
737
738 do
739 {
740 // Create a new EAPOL frame if we don't have one to retransmit
741 //if (aniAsfPacketGetLen(fsm->lastEapol) == 0)
742#if 0
743 if( fsm->lastEapol )
744 {
745 aniAsfPacketFree( fsm->lastEapol );
746 fsm->lastEapol = NULL;
747
748 retVal = aniAsfPacketAllocateExplicit(&fsm->lastEapol,
749 RSN_MAX_PACKET_SIZE,
750 EAPOL_TX_HEADER_SIZE );
751#endif
752 aniAsfPacketEmptyExplicit(fsm->lastEapol,
753 EAPOL_TX_HEADER_SIZE);
754 // }
755
756 if (1)
757 {
758
759 vos_mem_zero( &txDesc, sizeof(txDesc) );
760
761 // The Key Information bits...
762 if (fsm->staCtx->pwCipherType == eCSR_ENCRYPT_TYPE_AES)
763 {
764 txDesc.info.keyDescVers = ANI_EAPOL_KEY_DESC_VERS_AES;
765 }
766 else {
767 txDesc.info.keyDescVers = ANI_EAPOL_KEY_DESC_VERS_RC4;
768 }
769 txDesc.info.unicastFlag = eANI_BOOLEAN_TRUE;
770 txDesc.info.installFlag = eANI_BOOLEAN_TRUE;
771 txDesc.info.ackFlag = eANI_BOOLEAN_TRUE;
772 txDesc.info.micFlag = eANI_BOOLEAN_TRUE;
773
774 txDesc.keyLen = aagGetKeyMaterialLen(fsm->staCtx->pwCipherType);
775 aniSsmReplayCtrNext(fsm->staCtx->localReplayCtr, txDesc.replayCounter);
776 vos_mem_copy(txDesc.keyNonce, fsm->aNonce, sizeof(txDesc.keyNonce));
777
778 // Add the RSN IE (but not any WPA IE)
779 rsnWpaIeLen = getRsnIeFromAdvertizedIes(fsm, &rsnWpaIe);
780
781 if( !ANI_IS_STATUS_SUCCESS( rsnWpaIeLen) ) break;
782
783 retVal = aniAsfPacketAppendBuffer(keyData, rsnWpaIe, rsnWpaIeLen);
784 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
785
786 // Add the RSN group key encapsulation
787 retVal = aagAppendGroupKeyForRsn ( keyData );
788
789 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
790
791 groupKeyLen = aniAsfPacketGetBytes(keyData, &groupKeyBytes);
792 if( !ANI_IS_STATUS_SUCCESS( groupKeyLen ) )
793 {
794 retVal = ANI_E_FAILED;
795 break;
796 }
797
798 txDesc.info.secureFlag = eANI_BOOLEAN_TRUE;
799 txDesc.info.encKeyDataFlag = eANI_BOOLEAN_TRUE;
800
801 if ( fsm->staCtx->pwCipherType == eCSR_ENCRYPT_TYPE_AES )
802 {
803 /*
804 * Use the AES key wrap algorithm if either one of the pairwise
805 * key or the group key is an AES key.
806 *
807 * If the key being sent is not a multiple of
808 * ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE, then pad it with
809 * zeroes. e.g., if we are sending a WEP key of 5 or 13
810 * bytes.
811 */
812 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
813 "AES Key Wrap invoked. groupKeyLen = %d", groupKeyLen);
814
815 padLen = groupKeyLen % ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE;
816 if (padLen != 0) {
817 padLen = ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE - padLen;
818
819 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
820 "Before AES Key Wrap: padLen = %d", padLen);
821
822 if (groupKeyLen + padLen > sizeof(paddedGroupKeyEncaps)) {
823#if 0
824 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
825 "Cannot encode group key encapsulation of len %d and cipher type %s "
826 "to send to %s %s (aid %d, radio %d, user %s)",
827 groupKeyLen,
828 aniSsmIntGetCipherStr(AAG_GROUP_CIPHER(fsm->ctx->radioId)),
829 (fsm->ctx->bpIndicator ? "BP" : "STA"),
830 aniAsfHexStr(fsm->ctx->suppMac, sizeof(tAniMacAddr)),
831 fsm->ctx->aid,
832 fsm->ctx->radioId,
833 aagGetStaUserId(fsm->ctx));
834#endif
835 retVal = ANI_E_FAILED;
836 }
837 // OK, after you compute the pad length, you need to
838 // add the padding - 0xdd followed by 0x00's
839 addPad( groupKeyBytes , groupKeyLen , padLen );
840 // add the padding length
841 groupKeyLen += padLen;
842 // IMMEDIATELY adjust the packet size to reflect the pad
843 aniAsfPacketMoveRight(keyData, padLen);
844 if( !ANI_IS_STATUS_SUCCESS( retVal) ) break;
845 }
846
847 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
848 "Before AES Key Wrap: padded groupKeyLen = %d", groupKeyLen);
849
850 retVal = aniSsmAesKeyWrap(fsm->cryptHandle, groupKeyBytes, groupKeyLen,
851 fsm->staCtx->ptk + ANI_EAPOL_KEY_RSN_MIC_SIZE,
852 ANI_EAPOL_KEY_RSN_ENC_KEY_SIZE,
853 &wrappedKey);
854 if( !ANI_IS_STATUS_SUCCESS( retVal) ) break;
855 // This doesn't work...
856 //groupKeyBytes = wrappedKey;
857 //groupKeyLen += ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE;
858 // ...here is the right way to do it
859 // Add the length of the prepended IV A[0]
860 if (NULL == wrappedKey)
861 {
862 break;
863 }
864 groupKeyLen += ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE;
Rajesh Babu Prathipati4c347592014-07-01 18:46:42 +0530865 vos_mem_copy( groupKeyBytes, wrappedKey, groupKeyLen);
Jeff Johnson295189b2012-06-20 16:38:30 -0700866 // Free the array used to hold the wrapped key
867 if (wrappedKey) vos_mem_free( wrappedKey);
868 // IMMEDIATELY adjust the packet size to reflect the IV
869 aniAsfPacketMoveRight(keyData, ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE);
870 }
871 else {
872
873 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
874 "Auth RC4 Key Wrap invoked. groupKeyLen = %d", groupKeyLen);
875 }
876 txDesc.keyDataLen = aniAsfPacketGetBytes(keyData, &txDesc.keyData);
877
878 retVal = aniEapolWriteKey(fsm->cryptHandle,
879 fsm->lastEapol,
880 fsm->staCtx->suppMac,
881 fsm->staCtx->authMac,
882 ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW,
883 &txDesc,
884 fsm->staCtx->ptk,
885 CSR_AES_KEY_LEN);
886 if( !ANI_IS_STATUS_SUCCESS( retVal) ) break;
887 }
888 else {
889 retransmit = eANI_BOOLEAN_TRUE;
890 }
891
892 if( VOS_IS_STATUS_SUCCESS( bapRsnSendEapolFrame( fsm->ctx->pvosGCtx, fsm->lastEapol ) ) )
893 {
894 retVal = ANI_OK;
895 }
896 else
897 {
898 //we fail to send the eapol frame disconnect
899 bapAuthDisconnect( fsm->ctx );
900 retVal = ANI_ERROR;
901 }
902
903 }while( 0 );
904
905 return retVal;
906}
907
908static int
909gotoStatePtkInitDone(tAuthRsnFsm *fsm, tAniEapolKeyAvailEventData *data)
910{
911 int retVal;
912 tAniEapolRsnKeyDesc *rxDesc;
913 tCsrRoamSetKey setKeyInfo;
914
915 fsm->currentState = PTK_INIT_DONE;
916
917 rxDesc = data->keyDesc;
918
919 vos_mem_zero( &setKeyInfo, sizeof( tCsrRoamSetKey ) );
920 setKeyInfo.encType = eCSR_ENCRYPT_TYPE_AES;
921 setKeyInfo.keyDirection = eSIR_TX_RX;
922 vos_mem_copy( setKeyInfo.peerMac, fsm->staCtx->suppMac, sizeof( tAniMacAddr ) );
923 setKeyInfo.paeRole = 0; //this is a supplicant
924 setKeyInfo.keyId = 0; //always
925 setKeyInfo.keyLength = CSR_AES_KEY_LEN;
926 vos_mem_copy( setKeyInfo.Key, (v_U8_t *)fsm->staCtx->ptk + (2 * CSR_AES_KEY_LEN ), CSR_AES_KEY_LEN );
927 //fsm->suppCtx->ptk contains the 3 16-bytes keys. We need the last one.
928 if( VOS_IS_STATUS_SUCCESS( bapSetKey( fsm->ctx->pvosGCtx, &setKeyInfo ) ) )
929 {
930 //Done
931 aniAsfPacketEmptyExplicit(fsm->lastEapol, EAPOL_TX_HEADER_SIZE);
932 retVal = ANI_OK;
933 }
934 else
935 {
936 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "Auth: gotoStatePtkInitDone fail to set key\n" );
937 retVal = ANI_ERROR;
938 }
939
940 return retVal;
941}
942
943static int
944gotoStateUpdateKeysReq(tAuthRsnFsm *fsm, tAniEapolKeyAvailEventData *data)
945{
946 tAniEapolRsnKeyDesc *rxDesc;
947
948 fsm->currentState = UPDATE_KEYS_REQ;
949
950 rxDesc = data->keyDesc;
951
952 aniSsmReplayCtrUpdate(fsm->staCtx->peerReplayCtr, rxDesc->replayCounter);
953
954 checkTransition(fsm, data);
955
956 return ANI_OK;
957}
958
959static int
960gotoStateIntegFailure(tAuthRsnFsm *fsm, tSirMicFailureInfo *micFailureInfo)
961{
962 fsm->currentState = INTEG_FAILURE;
963
964 fsm->integFailed = eANI_BOOLEAN_FALSE;
965
966 checkTransition(fsm, NULL); // UCT
967
968 return ANI_OK;
969}
970
971static int
972gotoStateKeyUpdate(tAuthRsnFsm *fsm)
973{
974 fsm->currentState = KEY_UPDATE;
975
976 if( VOS_IS_STATUS_SUCCESS( vos_rand_get_bytes(fsm->cryptHandle, fsm->aNonce, ANI_EAPOL_KEY_RSN_NONCE_SIZE) ) )
977 {
978
979 // Replay counter will be automatically updated when we create a
980 // new packet
981
982 checkTransition(fsm, NULL); // UCT
983
984 return ANI_OK;
985 }
986 return ANI_ERROR;
987}
988
989static int
990gotoStateDisconnect(tAuthRsnFsm *fsm)
991{
992 fsm->currentState = DISCONNECT;
993
994 //What else do we need to clean up? Or BAP will call our vleanup function?
995
996 // FSM does not exist after this...
997 bapAuthDisconnect( fsm->ctx );
998
999 return ANI_OK;
1000}
1001
1002static
1003int zeroOutPtk(tAuthRsnFsm *fsm)
1004{
1005 return ANI_OK;
1006}
1007
1008static
1009int stopAllTimers(tAuthRsnFsm *fsm)
1010{
1011 vos_timer_stop( &fsm->msg2Timer );
1012 vos_timer_stop( &fsm->msg4Timer );
1013
1014 return ANI_OK;
1015}
1016
1017static
1018int derivePtk(tAuthRsnFsm *fsm, tAniEapolKeyAvailEventData *data)
1019{
1020 v_U32_t prfLen;
1021 tAniEapolRsnKeyDesc *rxDesc;
1022
1023 VOS_ASSERT(fsm->staCtx->pmk);
1024
1025 switch (fsm->staCtx->pwCipherType)
1026 {
1027 case eCSR_ENCRYPT_TYPE_AES:
1028 prfLen = AAG_RSN_PTK_PRF_LEN_CCMP;
1029 break;
1030 default:
1031 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
1032 "Auth cannot generate PTK for invalid algorithm %d\n",
1033 fsm->staCtx->pwCipherType);
1034 return ANI_E_ILLEGAL_ARG;
1035 break;
1036 };
1037
1038 rxDesc = (tAniEapolRsnKeyDesc *) data->keyDesc;
1039 return aagPtkPrf(fsm->cryptHandle,
1040 fsm->staCtx->ptk,
1041 prfLen,
1042 fsm->staCtx->pmk,
1043 fsm->staCtx->authMac,
1044 fsm->staCtx->suppMac,
1045 fsm->aNonce,
1046 rxDesc->keyNonce);
1047}
1048
1049static int
1050checkMic(tAuthRsnFsm *fsm,
1051 tAniEapolKeyAvailEventData *data)
1052{
1053 int retVal;
1054
1055 retVal = aniEapolKeyCheckMic(fsm->cryptHandle,
1056 data->eapolFrame,
1057 ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW,
1058 data->keyDesc,
1059 fsm->staCtx->ptk,
1060 CSR_AES_KEY_LEN);
1061
1062 if (retVal == ANI_E_MIC_FAILED)
1063 {
1064
1065 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
1066 "Auth failed EAPOL-MIC check in pairwise key exchange!\n");
1067 }
1068
1069 return retVal;
1070}
1071
1072static int
1073checkLocalReplayCounter(tAuthRsnFsm *fsm,
1074 tAniEapolKeyAvailEventData *data)
1075{
1076 int retVal = ANI_E_NULL_VALUE;
1077 int cmp;
1078 tAniEapolRsnKeyDesc *rxDesc;
1079
1080 rxDesc = data->keyDesc;
1081 if( rxDesc )
1082 {
1083 cmp = aniSsmReplayCtrCmp(fsm->staCtx->localReplayCtr, rxDesc->replayCounter);
1084
1085 // The STA should have sent back the same replay ctr as in our request
1086 if (cmp != 0)
1087 {
1088 retVal = ANI_E_REPLAY_CHECK_FAILED;
1089 }
1090 else
1091 {
1092 retVal = ANI_OK;
1093 }
1094 }
1095
1096 return retVal;
1097}
1098
1099static
1100int checkPeerReplayCounter(tAuthRsnFsm *fsm,
1101 tAniEapolKeyAvailEventData *data)
1102{
1103 int retVal = ANI_E_NULL_VALUE;
1104 int cmp;
1105 tAniEapolRsnKeyDesc *rxDesc;
1106
1107 rxDesc = data->keyDesc;
1108 if( rxDesc )
1109 {
1110 cmp = aniSsmReplayCtrCmp(fsm->staCtx->peerReplayCtr, rxDesc->replayCounter);
1111
1112 // The STA should have sent a newer replay ctr than its old
1113 // request. The first message is exempted from the check.
1114 if (fsm->staCtx->pastFirstPeerRequest && cmp >= 0)
1115 {
1116 retVal = ANI_E_REPLAY_CHECK_FAILED;
1117 }
1118
1119 fsm->staCtx->pastFirstPeerRequest = eANI_BOOLEAN_TRUE;
1120 }
1121
1122 return retVal;
1123}
1124
1125static int checkInfoElement(tAuthRsnFsm *fsm,
1126 tAniEapolKeyAvailEventData *data)
1127{
1128 tAniEapolRsnKeyDesc *desc;
1129 v_U8_t *ieStaBytes;
1130 int ieStaLen;
1131
1132 desc = (tAniEapolRsnKeyDesc *) data->keyDesc;
1133 if( desc )
1134 {
1135 ieStaLen = aniAsfPacketGetBytes(fsm->staCtx->ieSta, &ieStaBytes);
1136 if( !ANI_IS_STATUS_SUCCESS( ieStaLen ) )
1137 {
1138 return ieStaLen;
1139 }
1140
1141 if ((desc->keyDataLen != ieStaLen) ||
1142 ( !vos_mem_compare(desc->keyData, ieStaBytes, ieStaLen-2) ))
1143 {
1144 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
1145 "Auth STA sent inconsistent RSN IE!\n");
1146 return ANI_E_FAILED;
1147 }
1148 // Copy RSN IE
1149 //vos_mem_copy(fsm->advertizedRsnIe, desc->keyData, ieStaLen);
1150 vos_mem_copy(fsm->advertizedRsnIe, ieStaBytes, ieStaLen);
1151
1152 return ANI_OK;
1153 }
1154 else
1155 {
1156 return ANI_E_NULL_VALUE;
1157 }
1158
1159}
1160
1161static
1162int checkTransition(tAuthRsnFsm *fsm, void *arg)
1163{
1164 int retVal;
1165 tAniEapolKeyAvailEventData *data;
1166 tAniEapolRsnKeyDesc *rxDesc;
1167 tSirMicFailureInfo *micFailureInfo;
1168
1169 if (fsm->disconnect)
1170 {
1171 stopAllTimers(fsm);
1172 gotoStateDisconnect(fsm);
1173 return ANI_OK;
1174 }
1175
1176 if (fsm->authReq)
1177 {
1178 stopAllTimers(fsm);
1179 gotoStateAuthentication(fsm);
1180 return ANI_OK;
1181 }
1182
1183 switch (fsm->currentState)
1184 {
1185 case INITIALIZE:
1186 break;
1187 case AUTHENTICATION:
1188 gotoStateAuthentication2(fsm);
1189 break;
1190 case AUTHENTICATION_2:
1191 gotoStateGetPsk( fsm );
1192 break;
1193 case GET_PSK:
1194 //We always have PMK otherwise BAP won't let us here
1195 gotoStatePtkStart(fsm);
1196 break;
1197 case PTK_START:
1198 if ( fsm->eapolAvail )
1199 {
1200 fsm->eapolAvail = eANI_BOOLEAN_FALSE;
1201 if (NULL == arg)
1202 {
1203 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
1204 "arg is NULL, exiting checkTransition()");
1205 return ANI_E_FAILED;
1206 }
1207 data = (tAniEapolKeyAvailEventData *) arg;
1208 retVal = checkLocalReplayCounter(fsm, data);
1209 if (retVal != ANI_OK)
1210 return ANI_OK; // Caller should not fail
1211 retVal = derivePtk(fsm, data);
1212 if( !ANI_IS_STATUS_SUCCESS( retVal ) )
1213 {
1214 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
1215 "Auth derivePtk failed with code %d!\n", retVal);
1216 return retVal;
1217 }
1218 retVal = checkMic(fsm, data);
1219 if (retVal != ANI_OK)
1220 {
1221 bapAuthDisconnect( fsm->ctx );
1222 return retVal;
1223 }
1224 retVal = gotoStatePtkInitNego(fsm, arg);
1225 }
1226 else if ( fsm->msg2TimeOut )
1227 {
1228 if (fsm->numTries <= authConsts.maxTries)
1229 {
1230 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
1231 "Auth Retransmitting EAPOL-Key Msg1\n");
1232 // Stay in the same state but repeat actions
1233 gotoStatePtkStart(fsm);
1234 }
1235 else {
1236 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
1237 "Auth failed to recv EAPOL-Key Msg2 "
1238 "Disconnecting...\n");
1239
1240 gotoStateDisconnect(fsm);
1241 }
1242 }
1243 break;
1244 case PTK_INIT_NEGO:
1245 if (NULL == arg)
1246 {
1247 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
1248 "arg is NULL, exiting checkTransition()");
1249 return ANI_E_FAILED;
1250 }
1251 data = (tAniEapolKeyAvailEventData *) arg;
1252 retVal = checkInfoElement(fsm, data);
1253 if (retVal != ANI_OK)
1254 {
1255 gotoStateDisconnect(fsm);
1256 }
1257 else {
1258 gotoStatePtkInitNegoTx(fsm);
1259 }
1260 break;
1261 case PTK_INIT_NEGO_TX:
1262 if (fsm->eapolAvail)
1263 {
1264 fsm->eapolAvail = eANI_BOOLEAN_FALSE;
1265 if (NULL == arg)
1266 {
1267 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
1268 "arg is NULL, exiting checkTransition()");
1269 return ANI_E_FAILED;
1270 }
1271 data = (tAniEapolKeyAvailEventData *) arg;
1272 retVal = checkLocalReplayCounter(fsm, data);
1273 if (retVal != ANI_OK)
1274 return ANI_OK; // Caller should not fail
1275 retVal = checkMic(fsm, data);
1276 if (retVal != ANI_OK)
1277 {
1278 bapAuthDisconnect( fsm->ctx );
1279 return retVal;
1280 }
1281 retVal = gotoStatePtkInitDone(fsm, data);
1282 } else if ( fsm->msg4TimeOut )
1283 {
1284 if (fsm->numTries <= authConsts.maxTries)
1285 {
1286 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
1287 "Auth retransmitting EAPOL-Key Msg3 \n");
1288 // Stay in the same state but repeat actions
1289 gotoStatePtkInitNegoTx(fsm);
1290 }
1291 else {
1292 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
1293 "Auth failed to recv EAPOL-Key Msg4 "
1294 "Disconnecting...\n" );
1295
1296 gotoStateDisconnect(fsm);
1297 }
1298 }
1299 break;
1300 case PTK_INIT_DONE:
1301 if (fsm->eapolAvail) {
1302
1303 fsm->eapolAvail = eANI_BOOLEAN_FALSE;
1304 if (NULL == arg)
1305 {
1306 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
1307 "arg is NULL, exiting checkTransition()");
1308 return ANI_E_FAILED;
1309 }
1310 data = (tAniEapolKeyAvailEventData *) arg;
1311 rxDesc = (tAniEapolRsnKeyDesc *) data->keyDesc;
1312
1313 if (rxDesc->info.requestFlag)
1314 {
1315
1316 retVal = checkPeerReplayCounter(fsm, data);
1317 if (retVal != ANI_OK)
1318 return ANI_OK; // Caller should not fail
1319
1320 retVal = checkMic(fsm, data);
1321 if (retVal != ANI_OK)
1322 {
1323 bapAuthDisconnect( fsm->ctx->pvosGCtx );
1324 return retVal;
1325 }
1326
1327 retVal = gotoStateUpdateKeysReq(fsm, arg);
1328 }
1329 }
1330 else if (fsm->integFailed) {
1331
1332 micFailureInfo = (tSirMicFailureInfo *) arg;
1333 gotoStateIntegFailure(fsm, arg);
1334
1335 }
1336 break;
1337 case UPDATE_KEYS_REQ:
1338
1339 if (NULL == arg)
1340 {
1341 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
1342 "arg is NULL, exiting checkTransition()");
1343 return ANI_E_FAILED;
1344 }
1345 data = (tAniEapolKeyAvailEventData *) arg;
1346 rxDesc = (tAniEapolRsnKeyDesc *) data->keyDesc;
1347
1348 if (rxDesc->info.errorFlag)
1349 {
1350
1351 /*
1352 * This was generated by a unicast packet sent from the AP to the STA/BP.
1353 * The TX address is the AP's address. The src address is lost.
1354 * If the STA is a BP, then the true dst is lost. We will treat
1355 * the dst field as the address of the reporter of the MIC failure.
1356 */
1357
1358 micFailureInfo = (tSirMicFailureInfo *) vos_mem_malloc( sizeof(tSirMicFailureInfo) );
1359 if( NULL == micFailureInfo )
1360 {
1361 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
1362 "Fail to allocate memory for AuthRsnFsm: %d\n",
1363 fsm->currentState);
1364 return ANI_E_MALLOC_FAILED;
1365 }
1366
1367 vos_mem_copy(micFailureInfo->taMacAddr, fsm->staCtx->authMac, sizeof(tAniMacAddr));
1368 vos_mem_copy(micFailureInfo->dstMacAddr, fsm->staCtx->suppMac, sizeof(tAniMacAddr));
1369 micFailureInfo->multicast = eANI_BOOLEAN_FALSE;
1370 // Copy whatever sequence number came in the EAPOL-key message
1371 vos_mem_copy(micFailureInfo->TSC, rxDesc->keyRecvSeqCounter, SIR_CIPHER_SEQ_CTR_SIZE);
1372 gotoStateIntegFailure(fsm, micFailureInfo);
1373 vos_mem_free(micFailureInfo);
1374 }
1375 else {
1376 // TBD: Untested. Why are local aNonce and local replyCtr not incremented in spec?
1377 gotoStatePtkStart(fsm);
1378 }
1379 break;
1380 case INTEG_FAILURE:
1381 gotoStateKeyUpdate(fsm);
1382 break;
1383 case KEY_UPDATE:
1384 gotoStatePtkStart(fsm);
1385 break;
1386 default:
1387 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
1388 "Nothing to do in this state for AuthRsnFsm: %d\n",
1389 fsm->currentState);
1390 // Catch all for states that need no change:
1391 // assert(eANI_BOOLEAN_FALSE && "Illegal AuthRsnFsm state!");
1392 return ANI_E_FAILED;
1393 }
1394
1395 return ANI_OK;
1396}
1397
1398
1399static void msg2TimerCallback( void *pv )
1400{
1401 tAuthRsnFsm *fsm = (tAuthRsnFsm *)pv;
1402 if (NULL == fsm)
1403 {
1404 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001405 "fsm is NULL in %s", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001406
1407 return;
1408 }
1409
1410 //Only when waiting for msg2
1411 if( PTK_START == fsm->currentState )
1412 {
1413 fsm->msg2TimeOut = eANI_BOOLEAN_TRUE;
1414 }
1415 //We may need to synchronize this call
1416 authRsnFsmProcessEvent( fsm, RSN_FSM_TIMER_EXPIRED, NULL );
1417}
1418
1419static void msg4TimerCallback( void *pv )
1420{
1421 tAuthRsnFsm *fsm = (tAuthRsnFsm *)pv;
1422 if (NULL == fsm)
1423 {
1424 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001425 "fsm is NULL in %s", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001426
1427 return;
1428 }
1429
1430 //Only when we are waiting for msg4
1431 if( PTK_INIT_NEGO_TX == fsm->currentState )
1432 {
1433 fsm->msg4TimeOut = eANI_BOOLEAN_TRUE;
1434 }
1435 //We may need to synchronize this call
1436 authRsnFsmProcessEvent( fsm, RSN_FSM_TIMER_EXPIRED, NULL );
1437}
1438
1439
1440//
1441//This function alwasy assume the incoming vos_packet is 802_3 frame.
1442static int authRsnRxFrameHandler( v_PVOID_t pvosGCtx, vos_pkt_t *pPacket )
1443{
1444 int retVal = ANI_ERROR;
1445 tAniPacket *pAniPacket;
1446 tBtampContext *ctx;
1447 tAuthRsnFsm *fsm;
1448
1449 /* Validate params */
1450 if ((pvosGCtx == NULL) || (NULL == pPacket))
1451 {
1452 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001453 "param is NULL in %s", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001454
1455 return retVal;
1456 }
1457
1458 ctx = (tBtampContext *)VOS_GET_BAP_CB( pvosGCtx );
1459 if (NULL == ctx)
1460 {
1461 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001462 "ctx is NULL in %s", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001463
1464 return retVal;
1465 }
1466
1467 fsm = &ctx->uFsm.authFsm;
1468 if (NULL == fsm)
1469 {
1470 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001471 "fsm is NULL in %s", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001472
1473 return retVal;
1474 }
1475
1476 do
1477 {
1478 //ToDO: We need to synchronize this. For now, use the simplest form, drop the packet comes later.
1479 if( fsm->fReceiving )
1480 {
1481 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
1482 " ******authRsnRxFrameHandler receive eapol packet while processing. Drop the new comer\n" );
1483 break;
1484 }
1485 fsm->fReceiving = VOS_TRUE;
1486 retVal = bapRsnFormPktFromVosPkt( &pAniPacket, pPacket );
1487 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
1488 //Now we can process the eapol frame
1489 //handler will free the pAniPacket
1490 bapRsnEapolHandler( fsm, pAniPacket, VOS_TRUE );
1491 }while( 0 );
1492
1493 fsm->fReceiving = VOS_FALSE;
1494 vos_pkt_return_packet( pPacket );
1495
1496 return retVal;
1497}
1498
1499
1500static int authRsnTxCompleteHandler( v_PVOID_t pvosGCtx, vos_pkt_t *pPacket, VOS_STATUS retStatus )
1501{
1502 tBtampContext *ctx = (tBtampContext *)VOS_GET_BAP_CB( pvosGCtx );
1503 tAuthRsnFsm *fsm;
1504
1505 vos_pkt_return_packet( pPacket );
1506 if (NULL == ctx)
1507 {
1508 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001509 "ctx is NULL in %s", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001510
1511 return ANI_ERROR;
1512 }
1513
1514 fsm = &ctx->uFsm.authFsm;
1515 if (NULL == fsm)
1516 {
1517 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001518 "fsm is NULL in %s", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001519
1520 return ANI_ERROR;
1521 }
1522
1523 if(!VOS_IS_STATUS_SUCCESS( retStatus ) )
1524 {
1525 //No need to do anything. Retransmit is handled by timeout
1526 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
1527 "Auth: TL Tx complete with error %d current state is %d \n", retStatus, fsm->currentState );
1528 }
1529 if( PTK_START == fsm->currentState )
1530 {
1531 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
1532 " Auth: start msg2 timer\n" );
1533 //Start msg2Timer
1534 fsm->numTries++;
1535 vos_timer_stop( &fsm->msg2Timer );
1536 vos_timer_start(&fsm->msg2Timer, authConsts.timeoutPeriod);
1537 }
1538 else if( ( PTK_INIT_NEGO == fsm->currentState ) ||
1539 ( PTK_INIT_NEGO_TX == fsm->currentState ) )
1540 {
1541 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
1542 " Auth: start msg4 timer\n" );
1543 fsm->numTries++;
1544 vos_timer_stop( &fsm->msg4Timer );
1545 vos_timer_start(&fsm->msg4Timer, authConsts.timeoutPeriod);
1546 }
1547
1548 return ANI_OK;
1549}
1550
1551
1552static int
1553authEapolKeyHandler( tAuthRsnFsm *fsm, tAniPacket *eapolFrame, tAniMacAddr staMac )
1554{
1555 int retVal;
1556
1557 int descType;
1558 void *keyDesc;
1559 tAniEapolRsnKeyDesc *rsnDesc;
1560 tAniEapolKeyAvailEventData data;
1561
1562 do
1563 {
1564 retVal = aniEapolParseKey(eapolFrame, &descType, &keyDesc);
1565 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
1566
1567 if ((descType == ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW)
1568 || (descType == ANI_EAPOL_KEY_DESC_TYPE_RSN))
1569 {
1570 rsnDesc = (tAniEapolRsnKeyDesc *) keyDesc;
1571 data.keyDesc = keyDesc;
1572 data.eapolFrame = eapolFrame;
1573 // Pass on the event to the RSN FSM only if it is for a pairwise key
1574 if (rsnDesc->info.unicastFlag)
1575 {
1576 retVal = authRsnFsmProcessEvent(fsm,
1577 RSN_FSM_EAPOL_FRAME_AVAILABLE,
1578 &data);
1579 }
1580 else {
1581 //Not worry about GTK stuff
1582 }
1583 }
1584 else {
1585
1586 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
1587 "Got unexpected legacy 802.1x RC4 Key message \n" );
1588 retVal = ANI_E_FAILED;
1589 break;
1590 }
1591 }while( 0 );
1592
1593 aniEapolKeyFreeDesc(descType, keyDesc);
1594 return retVal;
1595}
1596
1597
1598void authEapolHandler( tAuthRsnFsm *fsm, tAniPacket *eapolFrame,
1599 tAniMacAddr dstMac,
1600 tAniMacAddr srcMac,
1601 v_U8_t *type)
1602{
1603 switch (*type)
1604 {
1605 case ANI_EAPOL_TYPE_START:
1606 //No doing anything because we only support WPA2-PSK
1607 break;
1608 case ANI_EAPOL_TYPE_LOGOFF:
1609 //ignore
1610 break;
1611 case ANI_EAPOL_TYPE_KEY:
1612 authEapolKeyHandler(fsm, eapolFrame, srcMac);
1613 break;
1614 default:
1615 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
1616 "Auth: EAPOL type not implemented: 0x%.2x\n", *type);
1617 break;
1618 }
1619}