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