📄 wlc_key.c
字号:
if (key) { wlc_key_delete(wlc, bsscfg, key->idx); bsscfg->bss_def_keys[remove->index] = NULL; } } } /* remove a per station key */ else { if ((scb = wlc_scbfind(wlc, &remove->ea)) && scb->key) wlc_key_delete(wlc, bsscfg, WSEC_KEY_INDEX(wlc, scb->key)); else if (NBANDS(wlc) > 1 && (scb = wlc_scbfindband(wlc, &remove->ea, OTHERBANDUNIT(wlc))) && scb->key) wlc_key_delete(wlc, bsscfg, WSEC_KEY_INDEX(wlc, scb->key)); }}voidwlc_key_delete(wlc_info_t *wlc, wlc_bsscfg_t *bsscfg, int index){ bool prev_psallowed; struct scb *scb; wsec_key_t *key; ASSERT(index < WSEC_MAX_KEYS); key = WSEC_KEY(wlc, index); /* check if already deleted */ if (key == NULL) { WL_ERROR(("Key is Null index %d", index)); return; } /* call the tkip module key cleanup */ if (key->algo == CRYPTO_ALGO_TKIP) { WL_ERROR(("Key Algo is TKIP")); key->len = 0; wl_tkip_keyset(wlc->wl, key); } else WL_ERROR(("Key Algo is not TKIP")); if (BSSCFG_STA(bsscfg)) { /* If Pairwise key or Group key is removed sec port is closed */ prev_psallowed = PS_ALLOWED(wlc); wlc->wsec_portopen = FALSE; if (prev_psallowed && !PS_ALLOWED(wlc)) wlc_set_pmstate(wlc, FALSE); } /* if this is a paired key, clean up any scb pointers */ if (!ETHER_ISNULLADDR(&key->ea)) { if ((scb = wlc_scbfind(wlc, &key->ea)) && scb->key) { ASSERT(!bcmp(key->ea.octet, scb->ea.octet, ETHER_ADDR_LEN)); ASSERT(key == scb->key); scb->key = NULL; } if (NBANDS(wlc) > 1 && (scb = wlc_scbfindband(wlc, &key->ea, OTHERBANDUNIT(wlc))) && scb->key) { ASSERT(!bcmp(key->ea.octet, &scb->ea, ETHER_ADDR_LEN)); ASSERT(key == scb->key); scb->key = NULL; } } else { /* if this was the primary tx key, update wsec_index */ if (key->id == bsscfg->wsec_index) bsscfg->wsec_index = -1; } /* reset even if we deallocate to catch use after free */ wlc_key_reset(wlc, key); /* free the memory block for paired keys */ if (index >= WSEC_MAX_DEFAULT_KEYS) { MFREE(wlc->pub.osh, key, sizeof(wsec_key_t)); wlc->wsec_keys[index] = NULL; } wlc_key_update(wlc, bsscfg, index);}/* reset the given key to initial values */static voidwlc_key_reset(wlc_info_t *wlc, wsec_key_t *key){ ASSERT(WSEC_KEY_INDEX(wlc, key) < WSEC_MAX_KEYS); key->len = 0; key->flags = 0; key->algo = CRYPTO_ALGO_OFF; key->algo_hw = WSEC_ALGO_OFF; bzero(key->ea.octet, ETHER_ADDR_LEN);}voidwlc_scb_key_delete(wlc_info_t *wlc, struct scb *scb){ int key_index; wsec_key_t *key; key = wlc_scb_getkey(scb); if (!key) return; key_index = WSEC_KEY_INDEX(wlc, key); WL_WSEC(("wl%d: %s: deleting pairwise key %d for %s\n", wlc->pub.unit, __FUNCTION__, key_index, bcm_ether_ntoa(&scb->ea, eabuf))); /* note: the scb key pointer will be set to NULL by this function. */ wlc_key_delete(wlc, scb->bsscfg, key_index); /* if we are freeing up a hardware key, look for a scb using a softkey * to swap in to the hardware key slot */ if (key_index < WLC_MAX_WSEC_HW_KEYS(wlc) && !WLC_SW_KEYS(wlc)) { wlc_key_hw_reallocate(wlc, key_index); }}static voidwlc_key_hw_reallocate(wlc_info_t *wlc, int hw_index){ int i; int soft_index; uint max_used; struct scb *scb = NULL; wsec_key_t *key; uint bandunit; WL_TRACE(("wl%d: %s: hw_index = %d\n", wlc->pub.unit, __FUNCTION__, hw_index)); ASSERT(wlc->wsec_keys[hw_index] == NULL); /* * Find a candidate paired soft key to move into the hw key slot */ max_used = 0; soft_index = -1; for (i = WLC_MAX_WSEC_HW_KEYS(wlc); i < WLC_MAX_WSEC_KEYS(wlc); i++) { key = wlc->wsec_keys[i]; if (key == NULL) continue; /* do the scb lookup in both bands */ bandunit = wlc->band->bandunit; do { /* look up the scb for this key */ scb = wlc_scbfindband(wlc, &key->ea, bandunit); /* if this scb is the most recently used, remember the key index */ if (scb && (max_used < scb->used)) { max_used = scb->used; soft_index = i; } if (NBANDS(wlc) > 1) bandunit = (bandunit == 0) ? 1 : 0; } while (bandunit != wlc->band->bandunit); } /* return if no soft keys in use */ if (soft_index == -1) return; /* * A taker for the hw slot has been found. */ key = wlc->wsec_keys[soft_index]; WL_WSEC(("wl%d: %s: swapping soft key %d to hw key %d for MAC %s\n", wlc->pub.unit, __FUNCTION__, soft_index, hw_index, bcm_ether_ntoa(&key->ea, eabuf))); /* move the soft key to the hw slot */ wlc->wsec_keys[hw_index] = key; wlc->wsec_keys[soft_index] = NULL; key->idx = (uint8)hw_index; /* now push the new key info to the hw key */ wlc_key_update(wlc, scb->bsscfg, hw_index); /* clear out the soft key */ wlc_key_update(wlc, scb->bsscfg, soft_index);}voidwlc_key_iv_init(wlc_info_t *wlc, wsec_key_t *key, wsec_iv_t *initial_iv){ d11regs_t *regs = wlc->regs; uint16 r1, r2; int i; WL_TRACE(("wl%d: wlc_key_iv_init\n", wlc->pub.unit)); if (!wlc->pub.up) return; ASSERT(key); switch (key->algo) { case CRYPTO_ALGO_TKIP: break; case CRYPTO_ALGO_WEP1: case CRYPTO_ALGO_WEP128: /* initialize transmit IV to a ~random value to minimize IV re-use * at startup */ r1 = R_REG(®s->tsf_random); r2 = R_REG(®s->tsf_random); key->txiv.hi = ((r2 & 0xff) << 16) | (r1 & 0xff00) | (r1 & 0x00ff); key->txiv.lo = 0; /* WEP only uses hi */ /* rx IV is not used for WEP */ bzero(key->rxiv, sizeof(key->rxiv)); break; case CRYPTO_ALGO_AES_CCM: for (i = 0; i < WLC_NUMRXIVS; i ++) { if (initial_iv != NULL) { key->rxiv[i].hi = initial_iv->hi; key->rxiv[i].lo = initial_iv->lo; } else { key->rxiv[i].hi = 0; key->rxiv[i].lo = 0; } } key->txiv.hi = key->txiv.lo = 0; break; default: WL_ERROR(("wl%d: wlc_key_iv_init: unsupported algorithm %d\n", wlc->pub.unit, key->algo)); break; }}#define WLC_AES_EXTENDED_PACKET (1 << 5)#define WLC_AES_OCB_IV_MAX ((1 << 28) - 3)voidwlc_key_iv_update(wlc_info_t *wlc, wlc_bsscfg_t *bsscfg, wsec_key_t *key, uchar *buf, bool update){ int index; uint32 iv_tmp = 0; wsec_iv_t *txiv; ASSERT(key); /* group keys in WPA-NONE (IBSS only, AES and TKIP) use a global TXIV */ if ((bsscfg->WPA_auth & WPA_AUTH_NONE) && ETHER_ISNULLADDR(&key->ea)) txiv = &bsscfg->wpa_none_txiv; else txiv = &key->txiv; WL_WSEC(("wl%d: wlc_key_iv_update start: iv32 0x%08x iv16 0x%04x algo %d \n", wlc->pub.unit, txiv->hi, txiv->lo, key->algo)); index = key->id; switch (key->algo) { case CRYPTO_ALGO_AES_CCM: if (update) { txiv->lo++; if (txiv->lo == 0) txiv->hi++; } /* Add in control flags and properly format */ buf[0] = txiv->lo & 0xff; buf[1] = (txiv->lo >> 8) & 0xff; buf[2] = 0; buf[3] = (uint8)(((index & 3) << DOT11_KEY_INDEX_SHIFT) | WLC_AES_EXTENDED_PACKET); buf[4] = txiv->hi & 0xff; buf[5] = (txiv->hi >> 8) & 0xff; buf[6] = (txiv->hi >> 16) & 0xff; buf[7] = (txiv->hi >> 24) & 0xff; break; case CRYPTO_ALGO_AES_OCB_MPDU: case CRYPTO_ALGO_AES_OCB_MSDU: if (update) { if (txiv->hi >= (1 << 28) - 3) { txiv->hi = 0; } else { txiv->hi++; } } /* Deconstruct the IV */ buf[0] = txiv->hi & 0xff; buf[1] = (txiv->hi >> 8) & 0xff; buf[2] = (txiv->hi >> 16) & 0xff; buf[3] = (index & 3) << DOT11_KEY_INDEX_SHIFT; buf[3] |= (txiv->hi >> 24) & 0xf; break; case CRYPTO_ALGO_TKIP: break; case CRYPTO_ALGO_WEP1: case CRYPTO_ALGO_WEP128: { /* Handle WEP */ uint bad = 1; uchar x, y, z, a, b, B; if (WLC_CHECK_WEP_UPDATE(wlc, update)) { iv_tmp = txiv->hi; while (bad) { iv_tmp++; x = iv_tmp & 0xff; y = (iv_tmp >> 8) & 0xff; z = (iv_tmp >> 16) & 0xff; a = x + y; b = (x + y) - z; /* Avoid weak IVs used in several published WEP crackingtools. */ if (a <= WEP128_KEY_SIZE) continue; if (a == 1 && b == 2) continue; if ((y == RC4_STATE_NBYTES - 1) && (x > 2 && x <= WEP128_KEY_SIZE + 2)) continue; if (x == 1 && (y >= 2 && y <= ((WEP128_KEY_SIZE-1)/2 + 1))) continue; bad = 0; B = 1; while (B < WEP128_KEY_SIZE) { if ((a == B && b == (B + 1) * 2)) { bad++; break; } B += 2; } if (bad) continue; B = 3; while (B < WEP128_KEY_SIZE/2 + 3) { if ((x == B) && (y == (RC4_STATE_NBYTES-1)-x)) { bad++; break; } B++; } } buf[0] = x; buf[1] = y; buf[2] = z; buf[3] = index << DOT11_KEY_INDEX_SHIFT; txiv->hi = iv_tmp; } else { /* Don't update - just break down in 3 bytes */ buf[0] = txiv->hi & 0xff; buf[1] = (txiv->hi >> 8) & 0xff; buf[2] = (txiv->hi >> 16) & 0xff; buf[3] = index << DOT11_KEY_INDEX_SHIFT; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -