blob: ae0a42224d06d49c015f7e17f39f502cd0eb4f6d [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
2 * Copyright (c) 2013-2015 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.
20 */
21
22/*
23 * 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/*
29 *
30 * This file lim_utils.cc contains the utility functions
31 * LIM uses.
32 * Author: Chandra Modumudi
33 * Date: 02/13/02
34 * History:-
35 * Date Modified by Modification Information
36 * --------------------------------------------------------------------
37 */
38
39#include "ani_global.h"
40#include "wni_api.h"
41
42#include "sir_common.h"
43#include "wni_cfg.h"
44#include "cfg_api.h"
45
46#include "utils_api.h"
47#include "lim_utils.h"
48#include "lim_security_utils.h"
49#ifdef WLAN_FEATURE_VOWIFI_11R
50#include "lim_ft_defs.h"
51#endif
52#include "lim_session.h"
53
54#define LIM_SEED_LENGTH 16
55/*
56 * preauth node timeout value in interval of 10msec
57 */
58#define LIM_OPENAUTH_TIMEOUT 500
59
60/**
61 * lim_is_auth_algo_supported()
62 *
63 ***FUNCTION:
64 * This function is called in various places within LIM code
65 * to determine whether passed authentication algorithm is enabled
66 * or not
67 *
68 ***LOGIC:
69 *
70 ***ASSUMPTIONS:
71 * NA
72 *
73 ***NOTE:
74 * NA
75 *
76 * @param authType Indicates MAC based authentication type
77 * (eSIR_OPEN_SYSTEM or eSIR_SHARED_KEY)
78 * If Shared Key authentication to be used,
79 * 'Privacy Option Implemented' flag is also
80 * checked.
81 *
82 * @return true if passed authType is enabled else false
83 */
84uint8_t
85lim_is_auth_algo_supported(tpAniSirGlobal pMac, tAniAuthType authType,
86 tpPESession psessionEntry)
87{
88 uint32_t algoEnable, privacyOptImp;
89
90 if (authType == eSIR_OPEN_SYSTEM) {
91
92 if (LIM_IS_AP_ROLE(psessionEntry)) {
93 if ((psessionEntry->authType == eSIR_OPEN_SYSTEM)
94 || (psessionEntry->authType == eSIR_AUTO_SWITCH))
95 return true;
96 else
97 return false;
98 }
99
100 if (wlan_cfg_get_int(pMac, WNI_CFG_OPEN_SYSTEM_AUTH_ENABLE,
101 &algoEnable) != eSIR_SUCCESS) {
102 /**
103 * Could not get AuthAlgo1 Enable value
104 * from CFG. Log error.
105 */
106 lim_log(pMac, LOGE,
107 FL("could not retrieve AuthAlgo1 Enable value"));
108
109 return false;
110 } else
111 return ((algoEnable > 0 ? true : false));
112 } else {
113
114 if (LIM_IS_AP_ROLE(psessionEntry)) {
115 if ((psessionEntry->authType == eSIR_SHARED_KEY)
116 || (psessionEntry->authType == eSIR_AUTO_SWITCH))
117 algoEnable = true;
118 else
119 algoEnable = false;
120
121 } else
122
123 if (wlan_cfg_get_int
124 (pMac, WNI_CFG_SHARED_KEY_AUTH_ENABLE,
125 &algoEnable) != eSIR_SUCCESS) {
126 /**
127 * Could not get AuthAlgo2 Enable value
128 * from CFG. Log error.
129 */
130 lim_log(pMac, LOGE,
131 FL("could not retrieve AuthAlgo2 Enable value"));
132
133 return false;
134 }
135
136 if (LIM_IS_AP_ROLE(psessionEntry)) {
137 privacyOptImp = psessionEntry->privacy;
138 } else
139
140 if (wlan_cfg_get_int(pMac, WNI_CFG_PRIVACY_ENABLED,
141 &privacyOptImp) != eSIR_SUCCESS)
142 {
143 /**
144 * Could not get PrivacyOptionImplemented value
145 * from CFG. Log error.
146 */
147 lim_log(pMac, LOGE,
148 FL
149 ("could not retrieve PrivacyOptImplemented value"));
150
151 return false;
152 }
153 return (algoEnable && privacyOptImp);
154 }
155} /****** end lim_is_auth_algo_supported() ******/
156
157/**
158 * lim_init_pre_auth_list
159 *
160 ***FUNCTION:
161 * This function is called while starting a BSS at AP
162 * to initialize MAC authenticated STA list. This may also be called
163 * while joining/starting an IBSS if MAC authentication is allowed
164 * in IBSS mode.
165 *
166 ***LOGIC:
167 *
168 ***ASSUMPTIONS:
169 *
170 ***NOTE:
171 *
172 * @param pMac - Pointer to Global MAC structure
173 * @return None
174 */
175
176void lim_init_pre_auth_list(tpAniSirGlobal pMac)
177{
178 pMac->lim.pLimPreAuthList = NULL;
179
180} /*** end lim_init_pre_auth_list() ***/
181
182/**
183 * lim_delete_pre_auth_list
184 *
185 ***FUNCTION:
186 * This function is called cleanup Pre-auth list either on
187 * AP or on STA when moving from one persona to other.
188 *
189 ***LOGIC:
190 *
191 ***ASSUMPTIONS:
192 *
193 ***NOTE:
194 *
195 * @param pMac - Pointer to Global MAC structure
196 * @return None
197 */
198
199void lim_delete_pre_auth_list(tpAniSirGlobal pMac)
200{
201 struct tLimPreAuthNode *pCurrNode, *pTempNode;
202
203 pCurrNode = pTempNode = pMac->lim.pLimPreAuthList;
204 while (pCurrNode != NULL) {
205 pTempNode = pCurrNode->next;
206
207 PELOG1(lim_log(pMac, LOG1, FL("=====> lim_delete_pre_auth_list "));)
208 lim_release_pre_auth_node(pMac, pCurrNode);
209
210 pCurrNode = pTempNode;
211 }
212 pMac->lim.pLimPreAuthList = NULL;
213} /*** end lim_delete_pre_auth_list() ***/
214
215/**
216 * lim_search_pre_auth_list
217 *
218 ***FUNCTION:
219 * This function is called when Authentication frame is received
220 * by AP (or at a STA in IBSS supporting MAC based authentication)
221 * to search if a STA is in the middle of MAC Authentication
222 * transaction sequence.
223 *
224 ***LOGIC:
225 *
226 ***ASSUMPTIONS:
227 *
228 ***NOTE:
229 *
230 * @param macAddr - MAC address of the STA that sent
231 * Authentication frame.
232 *
233 * @return Pointer to pre-auth node if found, else NULL
234 */
235
236struct tLimPreAuthNode *lim_search_pre_auth_list(tpAniSirGlobal pMac,
237 tSirMacAddr macAddr)
238{
239 struct tLimPreAuthNode *pTempNode = pMac->lim.pLimPreAuthList;
240
241 while (pTempNode != NULL) {
242 if (cdf_mem_compare((uint8_t *) macAddr,
243 (uint8_t *) &pTempNode->peerMacAddr,
244 sizeof(tSirMacAddr)))
245 break;
246
247 pTempNode = pTempNode->next;
248 }
249
250 return pTempNode;
251} /*** end lim_search_pre_auth_list() ***/
252
253/**
254 * lim_delete_open_auth_pre_auth_node() - delete any stale preauth nodes
255 * @mac_ctx: Pointer to Global MAC structure
256 *
257 * This function is called to delete any stale preauth nodes on
258 * receiving authentication frame and existing preauth nodes
259 * reached the maximum allowed limit.
260 *
261 * Return: return true if any preauthnode deleted else false
262 */
263uint8_t
264lim_delete_open_auth_pre_auth_node(tpAniSirGlobal mac_ctx)
265{
266 struct tLimPreAuthNode *prev_node, *temp_node, *found_node;
267 uint8_t auth_node_freed = false;
268
269 temp_node = prev_node = mac_ctx->lim.pLimPreAuthList;
270
271 if (temp_node == NULL)
272 return auth_node_freed;
273
274 while (temp_node != NULL) {
275 if (temp_node->mlmState == eLIM_MLM_AUTHENTICATED_STATE &&
276 temp_node->authType == eSIR_OPEN_SYSTEM &&
277 (cdf_mc_timer_get_system_ticks() >
278 (LIM_OPENAUTH_TIMEOUT + temp_node->timestamp) ||
279 cdf_mc_timer_get_system_ticks() < temp_node->timestamp)) {
280 /* Found node to be deleted */
281 auth_node_freed = true;
282 found_node = temp_node;
283 if (mac_ctx->lim.pLimPreAuthList == temp_node) {
284 prev_node = mac_ctx->lim.pLimPreAuthList =
285 temp_node = found_node->next;
286 } else {
287 prev_node->next = temp_node->next;
288 temp_node = prev_node->next;
289 }
290
291 lim_release_pre_auth_node(mac_ctx, found_node);
292 } else {
293 prev_node = temp_node;
294 temp_node = prev_node->next;
295 }
296 }
297
298 return auth_node_freed;
299}
300
301/**
302 * lim_add_pre_auth_node
303 *
304 ***FUNCTION:
305 * This function is called at AP while sending Authentication
306 * frame2.
307 * This may also be called on a STA in IBSS if MAC authentication is
308 * allowed in IBSS mode.
309 *
310 ***LOGIC:
311 * Node is always added to the front of the list
312 *
313 ***ASSUMPTIONS:
314 *
315 ***NOTE:
316 *
317 * @param pMac - Pointer to Global MAC structure
318 * @param pAuthNode - Pointer to pre-auth node to be added to the list.
319 *
320 * @return None
321 */
322
323void lim_add_pre_auth_node(tpAniSirGlobal pMac, struct tLimPreAuthNode *pAuthNode)
324{
325 pMac->lim.gLimNumPreAuthContexts++;
326
327 pAuthNode->next = pMac->lim.pLimPreAuthList;
328
329 pMac->lim.pLimPreAuthList = pAuthNode;
330} /*** end lim_add_pre_auth_node() ***/
331
332/**
333 * lim_release_pre_auth_node
334 *
335 ***FUNCTION:
336 * This function is called to realease the accquired
337 * pre auth node from list.
338 *
339 ***LOGIC:
340 *
341 ***ASSUMPTIONS:
342 *
343 ***NOTE:
344 *
345 * @param pMac - Pointer to Global MAC structure
346 * @param pAuthNode - Pointer to Pre Auth node to be released
347 * @return None
348 */
349
350void lim_release_pre_auth_node(tpAniSirGlobal pMac, tpLimPreAuthNode pAuthNode)
351{
352 pAuthNode->fFree = 1;
353 MTRACE(mac_trace
354 (pMac, TRACE_CODE_TIMER_DEACTIVATE, NO_SESSION,
355 eLIM_PRE_AUTH_CLEANUP_TIMER));
356 tx_timer_deactivate(&pAuthNode->timer);
357 pMac->lim.gLimNumPreAuthContexts--;
358} /*** end lim_release_pre_auth_node() ***/
359
360/**
361 * lim_delete_pre_auth_node
362 *
363 ***FUNCTION:
364 * This function is called at AP when a pre-authenticated STA is
365 * Associated/Reassociated or when AuthFrame4 is received after
366 * Auth Response timeout.
367 * This may also be called on a STA in IBSS if MAC authentication and
368 * Association/Reassociation is allowed in IBSS mode.
369 *
370 ***LOGIC:
371 *
372 ***ASSUMPTIONS:
373 *
374 ***NOTE:
375 *
376 * @param pMac - Pointer to Global MAC structure
377 * @param peerMacAddr - MAC address of the STA that need to be deleted
378 * from pre-auth node list.
379 *
380 * @return None
381 */
382
383void lim_delete_pre_auth_node(tpAniSirGlobal pMac, tSirMacAddr macAddr)
384{
385 struct tLimPreAuthNode *pPrevNode, *pTempNode;
386
387 pTempNode = pPrevNode = pMac->lim.pLimPreAuthList;
388
389 if (pTempNode == NULL)
390 return;
391
392 if (cdf_mem_compare((uint8_t *) macAddr,
393 (uint8_t *) &pTempNode->peerMacAddr,
394 sizeof(tSirMacAddr))) {
395 /* First node to be deleted */
396
397 pMac->lim.pLimPreAuthList = pTempNode->next;
398
399 PELOG1(lim_log
400 (pMac, LOG1,
401 FL
402 ("=====> lim_delete_pre_auth_node : first node to delete"));
403 )
404 PELOG1(lim_log
405 (pMac, LOG1,
406 FL("Release data entry: %x id %d peer "), pTempNode,
407 pTempNode->authNodeIdx);
408 lim_print_mac_addr(pMac, macAddr, LOG1);
409 )
410 lim_release_pre_auth_node(pMac, pTempNode);
411
412 return;
413 }
414
415 pTempNode = pTempNode->next;
416
417 while (pTempNode != NULL) {
418 if (cdf_mem_compare((uint8_t *) macAddr,
419 (uint8_t *) &pTempNode->peerMacAddr,
420 sizeof(tSirMacAddr))) {
421 /* Found node to be deleted */
422
423 pPrevNode->next = pTempNode->next;
424
425 PELOG1(lim_log
426 (pMac, LOG1,
427 FL
428 ("=====> lim_delete_pre_auth_node : subsequent node to delete"));
429 lim_log(pMac, LOG1,
430 FL("Release data entry: %x id %d peer "),
431 pTempNode, pTempNode->authNodeIdx);
432 lim_print_mac_addr(pMac, macAddr, LOG1);
433 )
434 lim_release_pre_auth_node(pMac, pTempNode);
435
436 return;
437 }
438
439 pPrevNode = pTempNode;
440 pTempNode = pTempNode->next;
441 }
442
443 /* Should not be here */
444 /* Log error */
445 lim_log(pMac, LOGP, FL("peer not found in pre-auth list, addr= "));
446 lim_print_mac_addr(pMac, macAddr, LOGP);
447
448} /*** end lim_delete_pre_auth_node() ***/
449
450/**
451 * limRestoreFromPreAuthState
452 *
453 ***FUNCTION:
454 * This function is called on STA whenever an Authentication
455 * sequence is complete and state prior to auth need to be
456 * restored.
457 *
458 ***LOGIC:
459 * MLM_AUTH_CNF is prepared and sent to SME state machine.
460 * In case of restoring from pre-auth:
461 * - Channel Id is programmed at LO/RF synthesizer
462 * - BSSID is programmed at RHP
463 *
464 ***ASSUMPTIONS:
465 *
466 ***NOTE:
467 *
468 * @param pMac - Pointer to Global MAC structure
469 * @param resultCode - result of authentication attempt
470 * @return None
471 */
472
473void
474lim_restore_from_auth_state(tpAniSirGlobal pMac, tSirResultCodes resultCode,
475 uint16_t protStatusCode, tpPESession sessionEntry)
476{
477 tSirMacAddr currentBssId;
478 tLimMlmAuthCnf mlmAuthCnf;
479
480#ifdef FEATURE_WLAN_DIAG_SUPPORT
481 lim_diag_event_report(pMac, WLAN_PE_DIAG_AUTH_COMP_EVENT, sessionEntry,
482 resultCode, protStatusCode);
483#endif
484
485 cdf_mem_copy((uint8_t *) &mlmAuthCnf.peerMacAddr,
486 (uint8_t *) &pMac->lim.gpLimMlmAuthReq->peerMacAddr,
487 sizeof(tSirMacAddr));
488 mlmAuthCnf.authType = pMac->lim.gpLimMlmAuthReq->authType;
489 mlmAuthCnf.resultCode = resultCode;
490 mlmAuthCnf.protStatusCode = protStatusCode;
491
492 /* Update PE session ID */
493 mlmAuthCnf.sessionId = sessionEntry->peSessionId;
494
495 /* / Free up buffer allocated */
496 /* / for pMac->lim.gLimMlmAuthReq */
497 cdf_mem_free(pMac->lim.gpLimMlmAuthReq);
498 pMac->lim.gpLimMlmAuthReq = NULL;
499
500 sessionEntry->limMlmState = sessionEntry->limPrevMlmState;
501
502 MTRACE(mac_trace
503 (pMac, TRACE_CODE_MLM_STATE, sessionEntry->peSessionId,
504 sessionEntry->limMlmState));
505
506 /* 'Change' timer for future activations */
507 lim_deactivate_and_change_timer(pMac, eLIM_AUTH_FAIL_TIMER);
508
509 sir_copy_mac_addr(currentBssId, sessionEntry->bssId);
510
511 if (sessionEntry->limSmeState == eLIM_SME_WT_PRE_AUTH_STATE) {
512 pMac->lim.gLimPreAuthChannelNumber = 0;
513 }
514
515 lim_post_sme_message(pMac, LIM_MLM_AUTH_CNF, (uint32_t *) &mlmAuthCnf);
516} /*** end lim_restore_from_auth_state() ***/
517
518/**
519 * lim_encrypt_auth_frame()
520 *
521 ***FUNCTION:
522 * This function is called in lim_process_auth_frame() function
523 * to encrypt Authentication frame3 body.
524 *
525 ***LOGIC:
526 *
527 ***ASSUMPTIONS:
528 * NA
529 *
530 ***NOTE:
531 * NA
532 *
533 * @param pMac Pointer to Global MAC structure
534 * @param keyId key id to used
535 * @param pKey Pointer to the key to be used for encryption
536 * @param pPlainText Pointer to the body to be encrypted
537 * @param pEncrBody Pointer to the encrypted auth frame body
538 * @param keyLength 8 (WEP40) or 16 (WEP104)
539 * @return None
540 */
541
542void
543lim_encrypt_auth_frame(tpAniSirGlobal pMac, uint8_t keyId, uint8_t *pKey,
544 uint8_t *pPlainText, uint8_t *pEncrBody,
545 uint32_t keyLength)
546{
547 uint8_t seed[LIM_SEED_LENGTH], icv[SIR_MAC_WEP_ICV_LENGTH];
548
549 keyLength += 3;
550
551 /* Bytes 3-7 of seed is key */
552 cdf_mem_copy((uint8_t *) &seed[3], pKey, keyLength - 3);
553
554 /* Compute CRC-32 and place them in last 4 bytes of plain text */
555 lim_compute_crc32(icv, pPlainText, sizeof(tSirMacAuthFrameBody));
556
557 cdf_mem_copy(pPlainText + sizeof(tSirMacAuthFrameBody),
558 icv, SIR_MAC_WEP_ICV_LENGTH);
559
560 /* Run RC4 on plain text with the seed */
561 lim_rc4(pEncrBody + SIR_MAC_WEP_IV_LENGTH,
562 (uint8_t *) pPlainText, seed, keyLength,
563 LIM_ENCR_AUTH_BODY_LEN - SIR_MAC_WEP_IV_LENGTH);
564
565 /* Prepare IV */
566 pEncrBody[0] = seed[0];
567 pEncrBody[1] = seed[1];
568 pEncrBody[2] = seed[2];
569 pEncrBody[3] = keyId << 6;
570} /****** end lim_encrypt_auth_frame() ******/
571
572/**
573 * lim_compute_crc32()
574 *
575 ***FUNCTION:
576 * This function is called to compute CRC-32 on a given source.
577 * Used while encrypting/decrypting Authentication frame 3.
578 *
579 ***LOGIC:
580 *
581 ***ASSUMPTIONS:
582 * NA
583 *
584 ***NOTE:
585 * NA
586 *
587 * @param pDest Destination location for computed CRC
588 * @param pSrc Source location to be CRC computed
589 * @param len Length over which CRC to be computed
590 * @return None
591 */
592
593void lim_compute_crc32(uint8_t *pDest, uint8_t *pSrc, uint8_t len)
594{
595 uint32_t crc;
596 int i;
597
598 crc = 0;
599 crc = ~crc;
600
601 while (len-- > 0)
602 crc = lim_crc_update(crc, *pSrc++);
603
604 crc = ~crc;
605
606 for (i = 0; i < SIR_MAC_WEP_IV_LENGTH; i++) {
607 pDest[i] = (uint8_t) crc;
608 crc >>= 8;
609 }
610} /****** end lim_compute_crc32() ******/
611
612/**
613 * lim_rc4()
614 *
615 ***FUNCTION:
616 * This function is called to run RC4 algorithm. Called while
617 * encrypting/decrypting Authentication frame 3.
618 *
619 ***LOGIC:
620 *
621 ***ASSUMPTIONS:
622 * NA
623 *
624 ***NOTE:
625 * NA
626 *
627 * @param pDest Destination location for encrypted text
628 * @param pSrc Source location to be encrypted
629 * @param seed Contains seed (IV + key) for PRNG
630 * @param keyLength 8 (WEP40) or 16 (WEP104)
631 * @param frameLen Length of the frame
632 *
633 * @return None
634 */
635
636void
637lim_rc4(uint8_t *pDest, uint8_t *pSrc, uint8_t *seed, uint32_t keyLength,
638 uint16_t frameLen)
639{
640 typedef struct {
641 uint8_t i, j;
642 uint8_t sbox[256];
643 } tRC4Context;
644
645 tRC4Context ctx;
646
647 {
648 uint16_t i, j, k;
649
650 /* */
651 /* Initialize sbox using seed */
652 /* */
653
654 ctx.i = ctx.j = 0;
655 for (i = 0; i < 256; i++)
656 ctx.sbox[i] = (uint8_t) i;
657
658 j = 0;
659 k = 0;
660 for (i = 0; i < 256; i++) {
661 uint8_t temp;
662 if (k < LIM_SEED_LENGTH)
663 j = (uint8_t) (j + ctx.sbox[i] + seed[k]);
664 temp = ctx.sbox[i];
665 ctx.sbox[i] = ctx.sbox[j];
666 ctx.sbox[j] = temp;
667
668 if (++k >= keyLength)
669 k = 0;
670 }
671 }
672
673 {
674 uint8_t i = ctx.i;
675 uint8_t j = ctx.j;
676 uint8_t len = (uint8_t) frameLen;
677
678 while (len-- > 0) {
679 uint8_t temp1, temp2;
680
681 i = (uint8_t) (i + 1);
682 temp1 = ctx.sbox[i];
683 j = (uint8_t) (j + temp1);
684
685 ctx.sbox[i] = temp2 = ctx.sbox[j];
686 ctx.sbox[j] = temp1;
687
688 temp1 = (uint8_t) (temp1 + temp2);
689 temp1 = ctx.sbox[temp1];
690 temp2 = (uint8_t) (pSrc ? *pSrc++ : 0);
691
692 *pDest++ = (uint8_t) (temp1 ^ temp2);
693 }
694
695 ctx.i = i;
696 ctx.j = j;
697 }
698} /****** end lim_rc4() ******/
699
700/**
701 * lim_decrypt_auth_frame()
702 *
703 ***FUNCTION:
704 * This function is called in lim_process_auth_frame() function
705 * to decrypt received Authentication frame3 body.
706 *
707 ***LOGIC:
708 *
709 ***ASSUMPTIONS:
710 * NA
711 *
712 ***NOTE:
713 * NA
714 *
715 * @param pMac Pointer to Global MAC structure
716 * @param pKey Pointer to the key to be used for decryption
717 * @param pEncrBody Pointer to the body to be decrypted
718 * @param pPlainBody Pointer to the decrypted body
719 * @param keyLength 8 (WEP40) or 16 (WEP104)
720 *
721 * @return Decrypt result - eSIR_SUCCESS for success and
722 * LIM_DECRYPT_ICV_FAIL for ICV mismatch.
723 * If decryption is a success, pBody will
724 * have decrypted auth frame body.
725 */
726
727uint8_t
728lim_decrypt_auth_frame(tpAniSirGlobal pMac, uint8_t *pKey, uint8_t *pEncrBody,
729 uint8_t *pPlainBody, uint32_t keyLength, uint16_t frameLen)
730{
731 uint8_t seed[LIM_SEED_LENGTH], icv[SIR_MAC_WEP_ICV_LENGTH];
732 int i;
733 keyLength += 3;
734
735 /* Bytes 0-2 of seed is received IV */
736 cdf_mem_copy((uint8_t *) seed, pEncrBody, SIR_MAC_WEP_IV_LENGTH - 1);
737
738 /* Bytes 3-7 of seed is key */
739 cdf_mem_copy((uint8_t *) &seed[3], pKey, keyLength - 3);
740
741 /* Run RC4 on encrypted text with the seed */
742 lim_rc4(pPlainBody,
743 pEncrBody + SIR_MAC_WEP_IV_LENGTH, seed, keyLength, frameLen);
744
745 PELOG4(lim_log(pMac, LOG4, FL("plainbody is "));
746 sir_dump_buf(pMac, SIR_LIM_MODULE_ID, LOG4, pPlainBody, frameLen);
747 )
748 /* Compute CRC-32 and place them in last 4 bytes of encrypted body */
749 lim_compute_crc32(icv,
750 (uint8_t *) pPlainBody,
751 (uint8_t) (frameLen - SIR_MAC_WEP_ICV_LENGTH));
752
753 /* Compare RX_ICV with computed ICV */
754 for (i = 0; i < SIR_MAC_WEP_ICV_LENGTH; i++) {
755 PELOG4(lim_log
756 (pMac, LOG4, FL(" computed ICV%d[%x], rxed ICV%d[%x]"),
757 i, icv[i], i,
758 pPlainBody[frameLen - SIR_MAC_WEP_ICV_LENGTH + i]);
759 )
760 if (icv[i] !=
761 pPlainBody[frameLen - SIR_MAC_WEP_ICV_LENGTH + i])
762 return LIM_DECRYPT_ICV_FAIL;
763 }
764
765 return eSIR_SUCCESS;
766} /****** end lim_decrypt_auth_frame() ******/
767
768/**
769 * lim_post_sme_set_keys_cnf
770 *
771 * A utility API to send MLM_SETKEYS_CNF to SME
772 */
773void lim_post_sme_set_keys_cnf(tpAniSirGlobal pMac,
774 tLimMlmSetKeysReq *pMlmSetKeysReq,
775 tLimMlmSetKeysCnf *mlmSetKeysCnf)
776{
777 /* Prepare and Send LIM_MLM_SETKEYS_CNF */
778 cdf_mem_copy((uint8_t *) &mlmSetKeysCnf->peerMacAddr,
779 (uint8_t *) pMlmSetKeysReq->peerMacAddr,
780 sizeof(tSirMacAddr));
781
782 cdf_mem_copy((uint8_t *) &mlmSetKeysCnf->peerMacAddr,
783 (uint8_t *) pMlmSetKeysReq->peerMacAddr,
784 sizeof(tSirMacAddr));
785
786 /* / Free up buffer allocated for mlmSetKeysReq */
787 cdf_mem_free(pMlmSetKeysReq);
788 pMac->lim.gpLimMlmSetKeysReq = NULL;
789
790 lim_post_sme_message(pMac,
791 LIM_MLM_SETKEYS_CNF, (uint32_t *) mlmSetKeysCnf);
792}
793
794/**
795 * lim_send_set_bss_key_req()
796 *
797 ***FUNCTION:
798 * This function is called from lim_process_mlm_set_keys_req(),
799 * when PE is trying to setup the Group Keys related
800 * to a specified encryption type
801 *
802 ***LOGIC:
803 *
804 ***ASSUMPTIONS:
805 * NA
806 *
807 ***NOTE:
808 * NA
809 *
810 * @param pMac Pointer to Global MAC structure
811 * @param pMlmSetKeysReq Pointer to MLM_SETKEYS_REQ buffer
812 * @return none
813 */
814void lim_send_set_bss_key_req(tpAniSirGlobal pMac,
815 tLimMlmSetKeysReq *pMlmSetKeysReq,
816 tpPESession psessionEntry)
817{
818 tSirMsgQ msgQ;
819 tpSetBssKeyParams pSetBssKeyParams = NULL;
820 tLimMlmSetKeysCnf mlmSetKeysCnf;
821 tSirRetStatus retCode;
822 uint32_t val = 0;
823
824 if (pMlmSetKeysReq->numKeys > SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS) {
825 lim_log(pMac, LOG1,
826 FL
827 ("numKeys = %d is more than SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS"),
828 pMlmSetKeysReq->numKeys);
829
830 /* Respond to SME with error code */
831 mlmSetKeysCnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
832 goto end;
833 }
834 /* Package WMA_SET_BSSKEY_REQ message parameters */
835
836 pSetBssKeyParams = cdf_mem_malloc(sizeof(tSetBssKeyParams));
837 if (NULL == pSetBssKeyParams) {
838 lim_log(pMac, LOGE,
839 FL("Unable to allocate memory during SET_BSSKEY"));
840
841 /* Respond to SME with error code */
842 mlmSetKeysCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
843 goto end;
844 } else
845 cdf_mem_set((void *)pSetBssKeyParams,
846 sizeof(tSetBssKeyParams), 0);
847
848 /* Update the WMA_SET_BSSKEY_REQ parameters */
849 pSetBssKeyParams->bssIdx = psessionEntry->bssIdx;
850 pSetBssKeyParams->encType = pMlmSetKeysReq->edType;
851
852 if (eSIR_SUCCESS != wlan_cfg_get_int(pMac, WNI_CFG_SINGLE_TID_RC, &val)) {
853 lim_log(pMac, LOGP, FL("Unable to read WNI_CFG_SINGLE_TID_RC"));
854 }
855
856 pSetBssKeyParams->singleTidRc = (uint8_t) val;
857
858 /* Update PE session Id */
859 pSetBssKeyParams->sessionId = psessionEntry->peSessionId;
860
861 pSetBssKeyParams->smesessionId = pMlmSetKeysReq->smesessionId;
862
863 if (pMlmSetKeysReq->key[0].keyId &&
864 ((pMlmSetKeysReq->edType == eSIR_ED_WEP40) ||
865 (pMlmSetKeysReq->edType == eSIR_ED_WEP104))
866 ) {
867 /* IF the key id is non-zero and encryption type is WEP, Send all the 4
868 * keys to HAL with filling the key at right index in pSetBssKeyParams->key. */
869 pSetBssKeyParams->numKeys = SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS;
870 cdf_mem_copy((uint8_t *) &pSetBssKeyParams->
871 key[pMlmSetKeysReq->key[0].keyId],
872 (uint8_t *) &pMlmSetKeysReq->key[0],
873 sizeof(pMlmSetKeysReq->key[0]));
874
875 } else {
876 pSetBssKeyParams->numKeys = pMlmSetKeysReq->numKeys;
877 cdf_mem_copy((uint8_t *) &pSetBssKeyParams->key,
878 (uint8_t *) &pMlmSetKeysReq->key,
879 sizeof(tSirKeys) * pMlmSetKeysReq->numKeys);
880 }
881
882 SET_LIM_PROCESS_DEFD_MESGS(pMac, false);
883 msgQ.type = WMA_SET_BSSKEY_REQ;
884 msgQ.reserved = 0;
885 msgQ.bodyptr = pSetBssKeyParams;
886 msgQ.bodyval = 0;
887
888 lim_log(pMac, LOGW, FL("Sending WMA_SET_BSSKEY_REQ..."));
889 MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type));
890 if (eSIR_SUCCESS != (retCode = wma_post_ctrl_msg(pMac, &msgQ))) {
891 lim_log(pMac, LOGE,
892 FL("Posting SET_BSSKEY to HAL failed, reason=%X"),
893 retCode);
894
895 /* Respond to SME with LIM_MLM_SETKEYS_CNF */
896 mlmSetKeysCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL;
897 } else
898 return; /* Continue after WMA_SET_BSSKEY_RSP... */
899
900end:
901 lim_post_sme_set_keys_cnf(pMac, pMlmSetKeysReq, &mlmSetKeysCnf);
902
903}
904
905/**
906 * @function : lim_send_set_sta_key_req()
907 *
908 * @brief : This function is called from lim_process_mlm_set_keys_req(),
909 * when PE is trying to setup the Unicast Keys related
910 * to a specified STA with specified encryption type
911 *
912 ***LOGIC:
913 *
914 ***ASSUMPTIONS:
915 * NA
916 *
917 ***NOTE:
918 * NA
919 *
920 * @param pMac Pointer to Global MAC structure
921 * @param pMlmSetKeysReq Pointer to MLM_SETKEYS_REQ buffer
922 * @param staIdx STA index for which the keys are being set
923 * @param defWEPIdx The default WEP key index [0..3]
924 * @return none
925 */
926void lim_send_set_sta_key_req(tpAniSirGlobal pMac,
927 tLimMlmSetKeysReq *pMlmSetKeysReq,
928 uint16_t staIdx,
929 uint8_t defWEPIdx,
930 tpPESession sessionEntry, bool sendRsp)
931{
932 tSirMsgQ msgQ;
933 tpSetStaKeyParams pSetStaKeyParams = NULL;
934 tLimMlmSetKeysCnf mlmSetKeysCnf;
935 tSirRetStatus retCode;
936 uint32_t val = 0;
937
938 /* Package WMA_SET_STAKEY_REQ message parameters */
939 pSetStaKeyParams = cdf_mem_malloc(sizeof(tSetStaKeyParams));
940 if (NULL == pSetStaKeyParams) {
941 lim_log(pMac, LOGP,
942 FL("Unable to allocate memory during SET_BSSKEY"));
943 return;
944 } else
945 cdf_mem_set((void *)pSetStaKeyParams, sizeof(tSetStaKeyParams),
946 0);
947
948 /* Update the WMA_SET_STAKEY_REQ parameters */
949 pSetStaKeyParams->staIdx = staIdx;
950 pSetStaKeyParams->encType = pMlmSetKeysReq->edType;
951
952 if (eSIR_SUCCESS != wlan_cfg_get_int(pMac, WNI_CFG_SINGLE_TID_RC, &val)) {
953 lim_log(pMac, LOGP, FL("Unable to read WNI_CFG_SINGLE_TID_RC"));
954 }
955
956 pSetStaKeyParams->singleTidRc = (uint8_t) val;
957
958 /* Update PE session ID */
959 pSetStaKeyParams->sessionId = sessionEntry->peSessionId;
960
961 /**
962 * For WEP - defWEPIdx indicates the default WEP
963 * Key to be used for TX
964 * For all others, there's just one key that can
965 * be used and hence it is assumed that
966 * defWEPIdx = 0 (from the caller)
967 */
968
969 pSetStaKeyParams->defWEPIdx = defWEPIdx;
970
971 pSetStaKeyParams->smesessionId = pMlmSetKeysReq->smesessionId;
972 cdf_mem_copy(pSetStaKeyParams->peerMacAddr,
973 pMlmSetKeysReq->peerMacAddr, sizeof(tSirMacAddr));
974
975 if (sendRsp == true) {
976 /** Store the Previous MlmState*/
977 sessionEntry->limPrevMlmState = sessionEntry->limMlmState;
978 SET_LIM_PROCESS_DEFD_MESGS(pMac, false);
979 }
980
981 if (LIM_IS_IBSS_ROLE(sessionEntry)
982 && !pMlmSetKeysReq->key[0].unicast) {
983 if (sendRsp == true)
984 sessionEntry->limMlmState =
985 eLIM_MLM_WT_SET_STA_BCASTKEY_STATE;
986 msgQ.type = WMA_SET_STA_BCASTKEY_REQ;
987 } else {
988 if (sendRsp == true)
989 sessionEntry->limMlmState =
990 eLIM_MLM_WT_SET_STA_KEY_STATE;
991 msgQ.type = WMA_SET_STAKEY_REQ;
992 }
993 MTRACE(mac_trace
994 (pMac, TRACE_CODE_MLM_STATE, sessionEntry->peSessionId,
995 sessionEntry->limMlmState));
996
997 /**
998 * In the Case of WEP_DYNAMIC, ED_TKIP and ED_CCMP
999 * the Key[0] contains the KEY, so just copy that alone,
1000 * for the case of WEP_STATIC the hal gets the key from cfg
1001 */
1002 switch (pMlmSetKeysReq->edType) {
1003 case eSIR_ED_WEP40:
1004 case eSIR_ED_WEP104:
1005 /* FIXME! Is this OK? */
1006 if (0 == pMlmSetKeysReq->numKeys) {
1007 uint32_t i;
1008
1009 for (i = 0; i < SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS; i++) {
1010 cdf_mem_copy((uint8_t *) &pSetStaKeyParams->
1011 key[i],
1012 (uint8_t *) &pMlmSetKeysReq->
1013 key[i], sizeof(tSirKeys));
1014 }
1015 pSetStaKeyParams->wepType = eSIR_WEP_STATIC;
1016 sessionEntry->limMlmState =
1017 eLIM_MLM_WT_SET_STA_KEY_STATE;
1018 MTRACE(mac_trace
1019 (pMac, TRACE_CODE_MLM_STATE,
1020 sessionEntry->peSessionId,
1021 sessionEntry->limMlmState));
1022 } else {
1023 /*This case the keys are coming from upper layer so need to fill the
1024 * key at the default wep key index and send to the HAL */
1025 if (defWEPIdx < SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS) {
1026 cdf_mem_copy((uint8_t *) &pSetStaKeyParams->
1027 key[defWEPIdx],
1028 (uint8_t *) &pMlmSetKeysReq->
1029 key[0],
1030 sizeof(pMlmSetKeysReq->key[0]));
1031 pMlmSetKeysReq->numKeys =
1032 SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS;
1033 } else {
1034 lim_log(pMac, LOGE, FL("Wrong Key Index %d"),
1035 defWEPIdx);
1036 cdf_mem_free(pSetStaKeyParams);
1037 return;
1038 }
1039 }
1040 break;
1041 case eSIR_ED_TKIP:
1042 case eSIR_ED_CCMP:
1043#ifdef FEATURE_WLAN_WAPI
1044 case eSIR_ED_WPI:
1045#endif
1046 {
1047 cdf_mem_copy((uint8_t *) &pSetStaKeyParams->key,
1048 (uint8_t *) &pMlmSetKeysReq->key[0],
1049 sizeof(tSirKeys));
1050 }
1051 break;
1052 default:
1053 break;
1054 }
1055
1056 pSetStaKeyParams->sendRsp = sendRsp;
1057
1058 msgQ.reserved = 0;
1059 msgQ.bodyptr = pSetStaKeyParams;
1060 msgQ.bodyval = 0;
1061
1062 lim_log(pMac, LOG1, FL("Sending WMA_SET_STAKEY_REQ..."));
1063 MTRACE(mac_trace_msg_tx(pMac, sessionEntry->peSessionId, msgQ.type));
1064 if (eSIR_SUCCESS != (retCode = wma_post_ctrl_msg(pMac, &msgQ))) {
1065 lim_log(pMac, LOGE,
1066 FL("Posting SET_STAKEY to HAL failed, reason=%X"),
1067 retCode);
1068 /* Respond to SME with LIM_MLM_SETKEYS_CNF */
1069 mlmSetKeysCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL;
1070 } else
1071 return; /* Continue after WMA_SET_STAKEY_RSP... */
1072
1073 if (sendRsp == true)
1074 lim_post_sme_set_keys_cnf(pMac, pMlmSetKeysReq, &mlmSetKeysCnf);
1075}