1 /*
2 * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /*
21 *
22 * This file lim_utils.cc contains the utility functions
23 * LIM uses.
24 * Author: Chandra Modumudi
25 * Date: 02/13/02
26 * History:-
27 * Date Modified by Modification Information
28 * --------------------------------------------------------------------
29 */
30
31 #include "ani_global.h"
32 #include "wni_api.h"
33
34 #include "sir_common.h"
35 #include "wni_cfg.h"
36
37 #include "utils_api.h"
38 #include "lim_utils.h"
39 #include "lim_security_utils.h"
40 #include "lim_ft_defs.h"
41 #include "lim_session.h"
42 #include <lim_assoc_utils.h>
43
44 #define LIM_SEED_LENGTH 16
45 /*
46 * preauth node timeout value in interval of 10msec
47 */
48 #define LIM_OPENAUTH_TIMEOUT 500
49
50 /**
51 * lim_is_auth_algo_supported()
52 *
53 ***FUNCTION:
54 * This function is called in various places within LIM code
55 * to determine whether passed authentication algorithm is enabled
56 * or not
57 *
58 ***LOGIC:
59 *
60 ***ASSUMPTIONS:
61 * NA
62 *
63 ***NOTE:
64 * NA
65 *
66 * @param authType Indicates MAC based authentication type
67 * (eSIR_OPEN_SYSTEM or eSIR_SHARED_KEY)
68 * If Shared Key authentication to be used,
69 * 'Privacy Option Implemented' flag is also
70 * checked.
71 *
72 * @return true if passed authType is enabled else false
73 */
74 uint8_t
lim_is_auth_algo_supported(struct mac_context * mac,tAniAuthType authType,struct pe_session * pe_session)75 lim_is_auth_algo_supported(struct mac_context *mac, tAniAuthType authType,
76 struct pe_session *pe_session)
77 {
78 bool algoEnable, privacyOptImp;
79 struct wlan_mlme_wep_cfg *wep_params = &mac->mlme_cfg->wep_params;
80
81 if (authType == eSIR_OPEN_SYSTEM) {
82
83 if (LIM_IS_AP_ROLE(pe_session)) {
84 if ((pe_session->authType == eSIR_OPEN_SYSTEM)
85 || (pe_session->authType == eSIR_AUTO_SWITCH))
86 return true;
87 else
88 return false;
89 }
90
91 algoEnable = wep_params->is_auth_open_system;
92 return algoEnable > 0 ? true : false;
93
94 } else {
95
96 if (LIM_IS_AP_ROLE(pe_session)) {
97 if ((pe_session->authType == eSIR_SHARED_KEY)
98 || (pe_session->authType == eSIR_AUTO_SWITCH))
99 algoEnable = true;
100 else
101 algoEnable = false;
102
103 } else {
104 algoEnable = wep_params->is_shared_key_auth;
105 }
106
107 if (LIM_IS_AP_ROLE(pe_session))
108 privacyOptImp = pe_session->privacy;
109 else
110 privacyOptImp = wep_params->is_privacy_enabled;
111
112 return algoEnable && privacyOptImp;
113 }
114 } /****** end lim_is_auth_algo_supported() ******/
115
116 /**
117 * lim_init_pre_auth_list
118 *
119 ***FUNCTION:
120 * This function is called while starting a BSS at AP
121 * to initialize MAC authenticated STA list. This may also be called
122 * while joining/starting an IBSS if MAC authentication is allowed
123 * in IBSS mode.
124 *
125 ***LOGIC:
126 *
127 ***ASSUMPTIONS:
128 *
129 ***NOTE:
130 *
131 * @param mac - Pointer to Global MAC structure
132 * @return None
133 */
134
lim_init_pre_auth_list(struct mac_context * mac)135 void lim_init_pre_auth_list(struct mac_context *mac)
136 {
137 mac->lim.pLimPreAuthList = NULL;
138
139 } /*** end lim_init_pre_auth_list() ***/
140
141 /**
142 * lim_delete_pre_auth_list
143 *
144 ***FUNCTION:
145 * This function is called cleanup Pre-auth list either on
146 * AP or on STA when moving from one persona to other.
147 *
148 ***LOGIC:
149 *
150 ***ASSUMPTIONS:
151 *
152 ***NOTE:
153 *
154 * @param mac - Pointer to Global MAC structure
155 * @return None
156 */
157
lim_delete_pre_auth_list(struct mac_context * mac)158 void lim_delete_pre_auth_list(struct mac_context *mac)
159 {
160 struct tLimPreAuthNode *pCurrNode, *pTempNode;
161
162 pCurrNode = pTempNode = mac->lim.pLimPreAuthList;
163 while (pCurrNode) {
164 pTempNode = pCurrNode->next;
165 lim_release_pre_auth_node(mac, pCurrNode);
166
167 pCurrNode = pTempNode;
168 }
169 mac->lim.pLimPreAuthList = NULL;
170 } /*** end lim_delete_pre_auth_list() ***/
171
172 /**
173 * lim_search_pre_auth_list
174 *
175 ***FUNCTION:
176 * This function is called when Authentication frame is received
177 * by AP (or at a STA in IBSS supporting MAC based authentication)
178 * to search if a STA is in the middle of MAC Authentication
179 * transaction sequence.
180 *
181 ***LOGIC:
182 *
183 ***ASSUMPTIONS:
184 *
185 ***NOTE:
186 *
187 * @param macAddr - MAC address of the STA that sent
188 * Authentication frame.
189 *
190 * @return Pointer to pre-auth node if found, else NULL
191 */
192
lim_search_pre_auth_list(struct mac_context * mac,tSirMacAddr macAddr)193 struct tLimPreAuthNode *lim_search_pre_auth_list(struct mac_context *mac,
194 tSirMacAddr macAddr)
195 {
196 struct tLimPreAuthNode *pTempNode = mac->lim.pLimPreAuthList;
197
198 while (pTempNode) {
199 if (!qdf_mem_cmp((uint8_t *) macAddr,
200 (uint8_t *) &pTempNode->peerMacAddr,
201 sizeof(tSirMacAddr)))
202 break;
203
204 pTempNode = pTempNode->next;
205 }
206
207 return pTempNode;
208 } /*** end lim_search_pre_auth_list() ***/
209
210 #ifdef WLAN_FEATURE_11BE_MLO
211 struct tLimPreAuthNode *
lim_search_pre_auth_list_by_mld_addr(struct mac_context * mac,tSirMacAddr mldaddr)212 lim_search_pre_auth_list_by_mld_addr(struct mac_context *mac,
213 tSirMacAddr mldaddr)
214 {
215 struct tLimPreAuthNode *pTempNode = mac->lim.pLimPreAuthList;
216
217 while (pTempNode) {
218 if (!qdf_mem_cmp((uint8_t *)mldaddr,
219 (uint8_t *)&pTempNode->peer_mld,
220 sizeof(tSirMacAddr)))
221 break;
222
223 pTempNode = pTempNode->next;
224 }
225
226 return pTempNode;
227 }
228 #endif
229
230 /**
231 * lim_delete_open_auth_pre_auth_node() - delete any stale preauth nodes
232 * @mac_ctx: Pointer to Global MAC structure
233 *
234 * This function is called to delete any stale preauth nodes on
235 * receiving authentication frame and existing preauth nodes
236 * reached the maximum allowed limit.
237 *
238 * Return: return true if any preauthnode deleted else false
239 */
240 uint8_t
lim_delete_open_auth_pre_auth_node(struct mac_context * mac_ctx)241 lim_delete_open_auth_pre_auth_node(struct mac_context *mac_ctx)
242 {
243 struct tLimPreAuthNode *prev_node, *temp_node, *found_node;
244 uint8_t auth_node_freed = false;
245
246 temp_node = prev_node = mac_ctx->lim.pLimPreAuthList;
247
248 if (!temp_node)
249 return auth_node_freed;
250
251 while (temp_node) {
252 if (temp_node->mlmState == eLIM_MLM_AUTHENTICATED_STATE &&
253 temp_node->authType == eSIR_OPEN_SYSTEM &&
254 (qdf_mc_timer_get_system_ticks() >
255 (LIM_OPENAUTH_TIMEOUT + temp_node->timestamp) ||
256 qdf_mc_timer_get_system_ticks() < temp_node->timestamp)) {
257 /* Found node to be deleted */
258 auth_node_freed = true;
259 found_node = temp_node;
260 if (mac_ctx->lim.pLimPreAuthList == temp_node) {
261 prev_node = mac_ctx->lim.pLimPreAuthList =
262 temp_node = found_node->next;
263 } else {
264 prev_node->next = temp_node->next;
265 temp_node = prev_node->next;
266 }
267
268 lim_release_pre_auth_node(mac_ctx, found_node);
269 } else {
270 prev_node = temp_node;
271 temp_node = prev_node->next;
272 }
273 }
274
275 return auth_node_freed;
276 }
277
278 /**
279 * lim_add_pre_auth_node
280 *
281 ***FUNCTION:
282 * This function is called at AP while sending Authentication
283 * frame2.
284 * This may also be called on a STA in IBSS if MAC authentication is
285 * allowed in IBSS mode.
286 *
287 ***LOGIC:
288 * Node is always added to the front of the list
289 *
290 ***ASSUMPTIONS:
291 *
292 ***NOTE:
293 *
294 * @param mac - Pointer to Global MAC structure
295 * @param pAuthNode - Pointer to pre-auth node to be added to the list.
296 *
297 * @return None
298 */
299
lim_add_pre_auth_node(struct mac_context * mac,struct tLimPreAuthNode * pAuthNode)300 void lim_add_pre_auth_node(struct mac_context *mac, struct tLimPreAuthNode *pAuthNode)
301 {
302 mac->lim.gLimNumPreAuthContexts++;
303
304 pAuthNode->next = mac->lim.pLimPreAuthList;
305
306 mac->lim.pLimPreAuthList = pAuthNode;
307 } /*** end lim_add_pre_auth_node() ***/
308
309 /**
310 * lim_release_pre_auth_node
311 *
312 ***FUNCTION:
313 * This function is called to release the acquired
314 * pre auth node from list.
315 *
316 ***LOGIC:
317 *
318 ***ASSUMPTIONS:
319 *
320 ***NOTE:
321 *
322 * @param mac - Pointer to Global MAC structure
323 * @param pAuthNode - Pointer to Pre Auth node to be released
324 * @return None
325 */
326
lim_release_pre_auth_node(struct mac_context * mac,tpLimPreAuthNode pAuthNode)327 void lim_release_pre_auth_node(struct mac_context *mac,
328 tpLimPreAuthNode pAuthNode)
329 {
330 pAuthNode->fFree = 1;
331 if (pAuthNode->authType == eSIR_AUTH_TYPE_SAE &&
332 pAuthNode->assoc_req.present) {
333 tpSirAssocReq assoc =
334 (tpSirAssocReq)pAuthNode->assoc_req.assoc_req;
335
336 lim_free_assoc_req_frm_buf(assoc);
337 qdf_mem_free(assoc);
338 pAuthNode->assoc_req.assoc_req = NULL;
339 pAuthNode->assoc_req.present = false;
340 }
341 MTRACE(mac_trace
342 (mac, TRACE_CODE_TIMER_DEACTIVATE, NO_SESSION,
343 eLIM_PRE_AUTH_CLEANUP_TIMER));
344 tx_timer_deactivate(&pAuthNode->timer);
345 mac->lim.gLimNumPreAuthContexts--;
346 } /*** end lim_release_pre_auth_node() ***/
347
348 /**
349 * lim_delete_pre_auth_node
350 *
351 ***FUNCTION:
352 * This function is called at AP when a pre-authenticated STA is
353 * Associated/Reassociated or when AuthFrame4 is received after
354 * Auth Response timeout.
355 * This may also be called on a STA in IBSS if MAC authentication and
356 * Association/Reassociation is allowed in IBSS mode.
357 *
358 ***LOGIC:
359 *
360 ***ASSUMPTIONS:
361 *
362 ***NOTE:
363 *
364 * @param mac - Pointer to Global MAC structure
365 * @param peerMacAddr - MAC address of the STA that need to be deleted
366 * from pre-auth node list.
367 *
368 * @return None
369 */
370
lim_delete_pre_auth_node(struct mac_context * mac,tSirMacAddr macAddr)371 void lim_delete_pre_auth_node(struct mac_context *mac, tSirMacAddr macAddr)
372 {
373 struct tLimPreAuthNode *pPrevNode, *pTempNode;
374
375 pTempNode = pPrevNode = mac->lim.pLimPreAuthList;
376
377 if (!pTempNode)
378 return;
379
380 if (!qdf_mem_cmp((uint8_t *) macAddr,
381 (uint8_t *) &pTempNode->peerMacAddr,
382 sizeof(tSirMacAddr))) {
383 /* First node to be deleted */
384
385 mac->lim.pLimPreAuthList = pTempNode->next;
386
387 pe_debug("fRelease data for %d peer "QDF_MAC_ADDR_FMT,
388 pTempNode->authNodeIdx,
389 QDF_MAC_ADDR_REF(macAddr));
390 lim_release_pre_auth_node(mac, pTempNode);
391
392 return;
393 }
394
395 pTempNode = pTempNode->next;
396
397 while (pTempNode) {
398 if (!qdf_mem_cmp((uint8_t *) macAddr,
399 (uint8_t *) &pTempNode->peerMacAddr,
400 sizeof(tSirMacAddr))) {
401 /* Found node to be deleted */
402
403 pPrevNode->next = pTempNode->next;
404
405 pe_debug("subsequent node to delete, Release data entry: %pK id %d peer "QDF_MAC_ADDR_FMT,
406 pTempNode, pTempNode->authNodeIdx,
407 QDF_MAC_ADDR_REF(macAddr));
408 lim_release_pre_auth_node(mac, pTempNode);
409
410 return;
411 }
412
413 pPrevNode = pTempNode;
414 pTempNode = pTempNode->next;
415 }
416
417 pe_err("peer not found in pre-auth list, addr= "QDF_MAC_ADDR_FMT,
418 QDF_MAC_ADDR_REF(macAddr));
419
420 } /*** end lim_delete_pre_auth_node() ***/
421
422 /**
423 * limRestoreFromPreAuthState
424 *
425 ***FUNCTION:
426 * This function is called on STA whenever an Authentication
427 * sequence is complete and state prior to auth need to be
428 * restored.
429 *
430 ***LOGIC:
431 * MLM_AUTH_CNF is prepared and sent to SME state machine.
432 * In case of restoring from pre-auth:
433 * - Channel Id is programmed at LO/RF synthesizer
434 * - BSSID is programmed at RHP
435 *
436 ***ASSUMPTIONS:
437 *
438 ***NOTE:
439 *
440 * @param mac - Pointer to Global MAC structure
441 * @param resultCode - result of authentication attempt
442 * @return None
443 */
444
445 void
lim_restore_from_auth_state(struct mac_context * mac,tSirResultCodes resultCode,uint16_t protStatusCode,struct pe_session * pe_session)446 lim_restore_from_auth_state(struct mac_context *mac, tSirResultCodes resultCode,
447 uint16_t protStatusCode, struct pe_session *pe_session)
448 {
449 tSirMacAddr currentBssId;
450 tLimMlmAuthCnf mlmAuthCnf;
451
452 #ifdef FEATURE_WLAN_DIAG_SUPPORT
453 lim_diag_event_report(mac, WLAN_PE_DIAG_AUTH_COMP_EVENT, pe_session,
454 resultCode, protStatusCode);
455 #endif
456
457 qdf_mem_copy((uint8_t *) &mlmAuthCnf.peerMacAddr,
458 (uint8_t *) &mac->lim.gpLimMlmAuthReq->peerMacAddr,
459 sizeof(tSirMacAddr));
460 mlmAuthCnf.authType = mac->lim.gpLimMlmAuthReq->authType;
461 mlmAuthCnf.resultCode = resultCode;
462 mlmAuthCnf.protStatusCode = protStatusCode;
463
464 /* Update PE session ID */
465 mlmAuthCnf.sessionId = pe_session->peSessionId;
466
467 /* / Free up buffer allocated */
468 /* / for mac->lim.gLimMlmAuthReq */
469 qdf_mem_free(mac->lim.gpLimMlmAuthReq);
470 mac->lim.gpLimMlmAuthReq = NULL;
471
472 pe_session->limMlmState = pe_session->limPrevMlmState;
473
474 MTRACE(mac_trace
475 (mac, TRACE_CODE_MLM_STATE, pe_session->peSessionId,
476 pe_session->limMlmState));
477
478 /*
479 * Set the auth_ack_status status flag as success as
480 * host have received the auth rsp and no longer auth
481 * retry is needed also cancel the auth rety timer
482 */
483 mac->auth_ack_status = LIM_ACK_RCD_SUCCESS;
484
485 /* Auth retry and AUth failure timers are not started for SAE */
486 /* 'Change' timer for future activations */
487 if (tx_timer_running(&mac->lim.lim_timers.
488 g_lim_periodic_auth_retry_timer))
489 lim_deactivate_and_change_timer(mac,
490 eLIM_AUTH_RETRY_TIMER);
491 /* 'Change' timer for future activations */
492 if (tx_timer_running(&mac->lim.lim_timers.gLimAuthFailureTimer))
493 lim_deactivate_and_change_timer(mac,
494 eLIM_AUTH_FAIL_TIMER);
495
496 sir_copy_mac_addr(currentBssId, pe_session->bssId);
497
498 if (pe_session->limSmeState == eLIM_SME_WT_PRE_AUTH_STATE) {
499 mac->lim.gLimPreAuthChannelNumber = 0;
500 }
501
502 lim_post_sme_message(mac, LIM_MLM_AUTH_CNF, (uint32_t *) &mlmAuthCnf);
503 } /*** end lim_restore_from_auth_state() ***/
504
505 /**
506 * lim_encrypt_auth_frame()
507 *
508 ***FUNCTION:
509 * This function is called in lim_process_auth_frame() function
510 * to encrypt Authentication frame3 body.
511 *
512 ***LOGIC:
513 *
514 ***ASSUMPTIONS:
515 * NA
516 *
517 ***NOTE:
518 * NA
519 *
520 * @param mac Pointer to Global MAC structure
521 * @param keyId key id to used
522 * @param pKey Pointer to the key to be used for encryption
523 * @param pPlainText Pointer to the body to be encrypted
524 * @param pEncrBody Pointer to the encrypted auth frame body
525 * @param keyLength 8 (WEP40) or 16 (WEP104)
526 * @return None
527 */
528
529 void
lim_encrypt_auth_frame(struct mac_context * mac,uint8_t keyId,uint8_t * pKey,uint8_t * pPlainText,uint8_t * pEncrBody,uint32_t keyLength)530 lim_encrypt_auth_frame(struct mac_context *mac, uint8_t keyId, uint8_t *pKey,
531 uint8_t *pPlainText, uint8_t *pEncrBody,
532 uint32_t keyLength)
533 {
534 uint8_t seed[LIM_SEED_LENGTH], icv[SIR_MAC_WEP_ICV_LENGTH];
535 uint16_t frame_len;
536
537 frame_len = ((tpSirMacAuthFrameBody)pPlainText)->length +
538 SIR_MAC_AUTH_FRAME_INFO_LEN + SIR_MAC_CHALLENGE_ID_LEN;
539 keyLength += 3;
540
541 /*
542 * Make sure that IV is non-zero, because few IOT APs fails to decrypt
543 * auth sequence 3 encrypted frames if initialization vector value is 0
544 */
545 qdf_get_random_bytes(seed, SIR_MAC_WEP_IV_LENGTH);
546 while (!(*(uint32_t *)seed))
547 qdf_get_random_bytes(seed, SIR_MAC_WEP_IV_LENGTH);
548
549 /* Bytes 3-7 of seed is key */
550 qdf_mem_copy((uint8_t *) &seed[3], pKey, keyLength - 3);
551
552 /* Compute CRC-32 and place them in last 4 bytes of plain text */
553 lim_compute_crc32(icv, pPlainText, frame_len);
554
555 qdf_mem_copy(pPlainText + frame_len,
556 icv, SIR_MAC_WEP_ICV_LENGTH);
557
558 /* Run RC4 on plain text with the seed */
559 lim_rc4(pEncrBody + SIR_MAC_WEP_IV_LENGTH,
560 (uint8_t *) pPlainText, seed, keyLength,
561 frame_len + SIR_MAC_WEP_ICV_LENGTH);
562
563 /* Prepare IV */
564 pEncrBody[0] = seed[0];
565 pEncrBody[1] = seed[1];
566 pEncrBody[2] = seed[2];
567 pEncrBody[3] = keyId << 6;
568 } /****** end lim_encrypt_auth_frame() ******/
569
570 /**
571 * lim_compute_crc32()
572 *
573 ***FUNCTION:
574 * This function is called to compute CRC-32 on a given source.
575 * Used while encrypting/decrypting Authentication frame 3.
576 *
577 ***LOGIC:
578 *
579 ***ASSUMPTIONS:
580 * NA
581 *
582 ***NOTE:
583 * NA
584 *
585 * @param pDest Destination location for computed CRC
586 * @param pSrc Source location to be CRC computed
587 * @param len Length over which CRC to be computed
588 * @return None
589 */
590
lim_compute_crc32(uint8_t * pDest,uint8_t * pSrc,uint16_t len)591 void lim_compute_crc32(uint8_t *pDest, uint8_t *pSrc, uint16_t len)
592 {
593 uint32_t crc;
594 int i;
595
596 crc = 0;
597 crc = ~crc;
598
599 while (len-- > 0)
600 crc = lim_crc_update(crc, *pSrc++);
601
602 crc = ~crc;
603
604 for (i = 0; i < SIR_MAC_WEP_IV_LENGTH; i++) {
605 pDest[i] = (uint8_t) crc;
606 crc >>= 8;
607 }
608 } /****** end lim_compute_crc32() ******/
609
610 /**
611 * lim_rc4()
612 *
613 ***FUNCTION:
614 * This function is called to run RC4 algorithm. Called while
615 * encrypting/decrypting Authentication frame 3.
616 *
617 ***LOGIC:
618 *
619 ***ASSUMPTIONS:
620 * NA
621 *
622 ***NOTE:
623 * NA
624 *
625 * @param pDest Destination location for encrypted text
626 * @param pSrc Source location to be encrypted
627 * @param seed Contains seed (IV + key) for PRNG
628 * @param keyLength 8 (WEP40) or 16 (WEP104)
629 * @param frameLen Length of the frame
630 *
631 * @return None
632 */
633
634 void
lim_rc4(uint8_t * pDest,uint8_t * pSrc,uint8_t * seed,uint32_t keyLength,uint16_t frameLen)635 lim_rc4(uint8_t *pDest, uint8_t *pSrc, uint8_t *seed, uint32_t keyLength,
636 uint16_t frameLen)
637 {
638 typedef struct {
639 uint8_t i, j;
640 uint8_t sbox[256];
641 } tRC4Context;
642
643 tRC4Context ctx;
644
645 {
646 uint16_t i, j, k;
647
648 /* */
649 /* Initialize sbox using seed */
650 /* */
651
652 ctx.i = ctx.j = 0;
653 for (i = 0; i < 256; i++)
654 ctx.sbox[i] = (uint8_t) i;
655
656 j = 0;
657 k = 0;
658 for (i = 0; i < 256; i++) {
659 uint8_t temp;
660
661 if (k < LIM_SEED_LENGTH)
662 j = (uint8_t) (j + ctx.sbox[i] + seed[k]);
663 temp = ctx.sbox[i];
664 ctx.sbox[i] = ctx.sbox[j];
665 ctx.sbox[j] = temp;
666
667 if (++k >= keyLength)
668 k = 0;
669 }
670 }
671
672 {
673 uint8_t i = ctx.i;
674 uint8_t j = ctx.j;
675 uint16_t len = frameLen;
676
677 while (len-- > 0) {
678 uint8_t temp1, temp2;
679
680 i = (uint8_t) (i + 1);
681 temp1 = ctx.sbox[i];
682 j = (uint8_t) (j + temp1);
683
684 ctx.sbox[i] = temp2 = ctx.sbox[j];
685 ctx.sbox[j] = temp1;
686
687 temp1 = (uint8_t) (temp1 + temp2);
688 temp1 = ctx.sbox[temp1];
689 temp2 = (uint8_t) (pSrc ? *pSrc++ : 0);
690
691 *pDest++ = (uint8_t) (temp1 ^ temp2);
692 }
693
694 ctx.i = i;
695 ctx.j = j;
696 }
697 } /****** end lim_rc4() ******/
698
699 /**
700 * lim_decrypt_auth_frame()
701 *
702 ***FUNCTION:
703 * This function is called in lim_process_auth_frame() function
704 * to decrypt received Authentication frame3 body.
705 *
706 ***LOGIC:
707 *
708 ***ASSUMPTIONS:
709 * NA
710 *
711 ***NOTE:
712 * NA
713 *
714 * @param mac Pointer to Global MAC structure
715 * @param pKey Pointer to the key to be used for decryption
716 * @param pEncrBody Pointer to the body to be decrypted
717 * @param pPlainBody Pointer to the decrypted body
718 * @param keyLength 8 (WEP40) or 16 (WEP104)
719 *
720 * @return Decrypt result - QDF_STATUS_SUCCESS for success and
721 * LIM_DECRYPT_ICV_FAIL for ICV mismatch.
722 * If decryption is a success, pBody will
723 * have decrypted auth frame body.
724 */
725
726 uint8_t
lim_decrypt_auth_frame(struct mac_context * mac,uint8_t * pKey,uint8_t * pEncrBody,uint8_t * pPlainBody,uint32_t keyLength,uint16_t frameLen)727 lim_decrypt_auth_frame(struct mac_context *mac, uint8_t *pKey, uint8_t *pEncrBody,
728 uint8_t *pPlainBody, uint32_t keyLength, uint16_t frameLen)
729 {
730 uint8_t seed[LIM_SEED_LENGTH], icv[SIR_MAC_WEP_ICV_LENGTH];
731 int i;
732
733 keyLength += 3;
734
735 /* Bytes 0-2 of seed is received IV */
736 qdf_mem_copy((uint8_t *) seed, pEncrBody, SIR_MAC_WEP_IV_LENGTH - 1);
737
738 /* Bytes 3-7 of seed is key */
739 qdf_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 /* Compute CRC-32 and place them in last 4 bytes of encrypted body */
746 lim_compute_crc32(icv,
747 (uint8_t *) pPlainBody,
748 (frameLen - SIR_MAC_WEP_ICV_LENGTH));
749
750 /* Compare RX_ICV with computed ICV */
751 for (i = 0; i < SIR_MAC_WEP_ICV_LENGTH; i++) {
752 pe_debug("computed ICV%d[%x], rxed ICV%d[%x]",
753 i, icv[i], i,
754 pPlainBody[frameLen - SIR_MAC_WEP_ICV_LENGTH + i]);
755
756 if (icv[i] !=
757 pPlainBody[frameLen - SIR_MAC_WEP_ICV_LENGTH + i])
758 return LIM_DECRYPT_ICV_FAIL;
759 }
760
761 return QDF_STATUS_SUCCESS;
762 } /****** end lim_decrypt_auth_frame() ******/
763