📄 wlc_security.c
字号:
/* * Assorted functions for Wireless Security * * Copyright 2005-2006, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * * $Id$ */#include <wlc_cfg.h>#include <typedefs.h>#include <bcmdefs.h>#define MBUFSIZE 4096 /* Max buffer size */#include <osl.h>#include <bcmutils.h>#include <bcmendian.h>#include <sbutils.h>#include <proto/802.11.h>#include <sbhndpio.h>#include <sbhnddma.h>#include <hnddma.h>#include <d11.h>#include <wlioctl.h>#include <wlc_key.h>#include <wlc_rate.h>#include <wlc_rate_sel.h>#include <wlc_channel.h>#include <wlc_pub.h>#include <wlc_bsscfg.h>#include <wlc_pio.h>#include <wlc.h>#include <wlc_scb.h>#include <wlc_security.h>#include <bcmwpa.h>#include <wlc_frmutil.h>#include <wl_export.h>/* 802.1X LLC header, * DSAP/SSAP/CTL = AA:AA:03 * OUI = 00:00:00 * Ethertype = 0x888e (802.1X Port Access Entity) */const uint8 wlc_802_1x_hdr[] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e};/* Check if the received frame passes security filter */boolwlc_wsec_recvdata(wlc_info_t *wlc, osl_t *osh, struct scb *scb, struct wlc_frminfo *f, uint8 prio){ struct wlc_bsscfg *bsscfg = SCB_BSSCFG(scb); uint8 ividx = f->ividx; /* unencrypted */ if (!f->rx_wep) { } /* encrypted */ else { uchar *piv = f->pbody; uint16 iv16 = 0; uint32 iv32 = 0; f->key_index = f->pbody[3] >> DOT11_KEY_INDEX_SHIFT; f->key = wlc_key_lookup(wlc, scb, bsscfg, f->key_index, f->ismulti); /* toss encrypted packets if we cannot decrypt them */ if (!(f->key && WSEC_ENABLED(bsscfg->wsec))) { if (!f->ismulti) { WL_ERROR(("wl%d: wlc_recvdata: unsupported encrypted unicast frame" " from %s\n", wlc->pub.unit, bcm_ether_ntoa(&(f->h->a2), (char*)addrstr))); } else { WL_WSEC(("wl%d: wlc_recvdata: unsupported encrypted multicast frame" " from %s\n", wlc->pub.unit, bcm_ether_ntoa(&(f->h->a2), (char*)addrstr))); } WLCNTINCR(wlc->pub._cnt.rxundec); WLCNTINCR(wlc->pub._cnt.wepundec); return FALSE; } WL_WSEC(("wl%d: wlc_wsec_recvdata: received encrypted frame\n", wlc->pub.unit)); /* If we havn't tossed the frame yet, we better have a key */ ASSERT(f->key); ASSERT(WSEC_KEY_INDEX(wlc, f->key) < WLC_MAX_WSEC_KEYS(wlc)); if (f->key->algo == CRYPTO_ALGO_TKIP) { int error; int hdr_len; /* call the software crypto decrypt routine */ f->rxh->RxStatus1 |= RXS_DECATMPT; hdr_len = ((uchar *)f->pbody - (uchar *)f->h); error = wl_tkip_decrypt(wlc->wl, f->p, hdr_len, f->ismulti); if (error < 0) { if (error == -4) WL_ERROR(("Replay detected\n")); else if (error == -5) WL_ERROR(("ICV Error detected\n")); else if (error == -6) WL_ERROR(("Invalid Key Index\n")); else if (error == -3) WL_ERROR(("Key not configured\n")); else if (error == -2) WL_ERROR(("Recd TKIP frame with out ExtIV flag\n")); else if (error == -1) WL_ERROR(("Invalid Len frame \n")); f->rxh->RxStatus1 |= RXS_DECERR; return FALSE; } /* linux kernel tkip module removes the iv and icv after the above routine returns */ f->h = (struct dot11_header *)(PKTDATA(osh, f->p)); f->pbody = (PKTDATA(osh, f->p) + hdr_len); } else if (f->key->algo == CRYPTO_ALGO_AES_CCM) { /* veryfy the replay counter */ iv16 = (piv[1] << 8) | piv[0]; iv32 = (piv[7] << 24) | (piv[6] << 16) | (piv[5] << 8) | (piv[4]); if ((f->WPA_auth & WPA_AUTH_NONE) == 0 && ((iv32 < f->key->rxiv[ividx].hi) || ((iv32 == f->key->rxiv[ividx].hi) && (iv16 < f->key->rxiv[ividx].lo)))) { WL_WSEC(("wl%d: wlc_recvdata: AES replay detected: ividx %d, got" " 0x%08x%04x, expected greater than or equal " "to 0x%08x%04x, retry 0x%x\n", wlc->pub.unit, ividx, iv32, iv16, f->key->rxiv[ividx].hi, f->key->rxiv[ividx].lo, f->fc & FC_RETRY)); WLCNTINCR(wlc->pub._cnt.rxundec); WLCNTINCR(wlc->pub._cnt.ccmpreplay); return FALSE; } WL_WSEC(("wl%d: wlc_recvdata: AES iv32 0x%08x iv16 0x%04x\n", wlc->pub.unit, iv32, iv16)); } f->body_len -= f->key->iv_len + f->key->icv_len; f->totlen -= f->key->iv_len + f->key->icv_len; f->len = PKTLEN(osh, f->p); if (f->key->algo != CRYPTO_ALGO_TKIP) { f->pbody += f->key->iv_len; /* strip off ICV from base packet */ f->len -= f->key->icv_len; /* store ivs */ f->iv32 = iv32; f->iv16 = iv16; PKTSETLEN(osh, f->p, f->len); } } return TRUE;}boolwlc_wsec_miccheck(wlc_info_t *wlc, osl_t *osh, struct scb *scb, struct wlc_frminfo *f){ wsec_key_t *key = f->key; int error; if (key->algo == CRYPTO_ALGO_TKIP) { WL_WSEC(("wl%d: wlc_recvdata: TKIP MIC check ...\n", wlc->pub.unit)); error = wl_tkip_miccheck(wlc->wl, f->p, ((uchar *)f->pbody - (uchar *)f->h), f->ismulti, key->id); if (error < 0) { WL_ERROR(("wl%d: Mic Check Failed %d\n", wlc->pub.unit, error)); wlc_mic_error(wlc, f->sa, f->ismulti, FALSE); wl_tkip_printstats(wlc->wl, f->ismulti); return FALSE; } } else if (key->algo == CRYPTO_ALGO_AES_CCM) { if (f->iv16 == 0xffff) key->rxiv[f->ividx].hi = f->iv32 + 1; else key->rxiv[f->ividx].hi = f->iv32; key->rxiv[f->ividx].lo = f->iv16 + 1; } return TRUE;}voidwlc_mic_error(wlc_info_t *wlc, struct ether_addr *addr, bool group, bool flush_txq){ wlc_event_t e; bzero(&e, sizeof(e)); e.event.event_type = WLC_E_MIC_ERROR; if (addr != NULL) { bcopy(addr->octet, e.event.addr.octet, ETHER_ADDR_LEN); e.addr = &(e.event.addr); } e.event.flags = (group?WLC_EVENT_MSG_GROUP:0) | (flush_txq?WLC_EVENT_MSG_FLUSHTXQ:0); wlc_event(wlc, &e);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -