void wep_dump(struct ieee80211_key *k, wbuf_t wbuf, int hdrlen) { struct ieee80211_frame *wh; struct wep_ctx *ctx = k->wk_private; struct ieee80211vap *vap = ctx->wc_vap; unsigned int iv,idx,icv; unsigned char *ptr; unsigned char kbuf[64]; wh = (struct ieee80211_frame *)wbuf_header(wbuf); ptr = (unsigned char*)wh; idx = iv = 0; memcpy(&iv, ptr+hdrlen, 3); idx = ptr[hdrlen+3]; memcpy(&icv, ptr+wbuf_get_pktlen(wbuf)-4, 4); memcpy(kbuf, k->wk_key, k->wk_keylen); IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr1, "%s and seq=%02x-%02x\n", "addr1", wh->i_seq[0], wh->i_seq[1]); IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr3, "%s", "addr3"); IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2, "IV=%08x idx=%d ICV=%08x, hdrlen=%d",iv, idx&0xff, icv, hdrlen); printk("key dump:len=%d\n", k->wk_keylen); dump_hex_buf(kbuf, (int)k->wk_keylen); printk("packet dump:pktlen=%d,len=%d\n", wbuf_get_pktlen(wbuf), wbuf_get_len(wbuf)); dump_hex_buf((uint8_t*)ptr/*wbuf_raw_data(wbuf)*/, (int)wbuf_get_pktlen(wbuf)); }
/* * Add privacy headers appropriate for the specified key. */ struct ieee80211_key * ieee80211_crypto_encap(struct ieee80211_node *ni, struct mbuf *m) { struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_key *k; struct ieee80211_frame *wh; const struct ieee80211_cipher *cip; uint8_t keyid; /* * Multicast traffic always uses the multicast key. * Otherwise if a unicast key is set we use that and * it is always key index 0. When no unicast key is * set we fall back to the default transmit key. */ wh = mtod(m, struct ieee80211_frame *); if (IEEE80211_IS_MULTICAST(wh->i_addr1) || IEEE80211_KEY_UNDEFINED(&ni->ni_ucastkey)) { if (vap->iv_def_txkey == IEEE80211_KEYIX_NONE) { IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr1, "no default transmit key (%s) deftxkey %u", __func__, vap->iv_def_txkey); vap->iv_stats.is_tx_nodefkey++; return NULL; } keyid = vap->iv_def_txkey; k = &vap->iv_nw_keys[vap->iv_def_txkey]; } else { keyid = 0; k = &ni->ni_ucastkey; } cip = k->wk_cipher; return (cip->ic_encap(k, m, keyid<<6) ? k : NULL); }
struct ieee80211_key * ieee80211_crypto_get_txkey(struct ieee80211_node *ni, struct mbuf *m) { struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_frame *wh; /* * Multicast traffic always uses the multicast key. * Otherwise if a unicast key is set we use that and * it is always key index 0. When no unicast key is * set we fall back to the default transmit key. */ wh = mtod(m, struct ieee80211_frame *); if (IEEE80211_IS_MULTICAST(wh->i_addr1) || IEEE80211_KEY_UNDEFINED(&ni->ni_ucastkey)) { if (vap->iv_def_txkey == IEEE80211_KEYIX_NONE) { IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr1, "no default transmit key (%s) deftxkey %u", __func__, vap->iv_def_txkey); vap->iv_stats.is_tx_nodefkey++; return NULL; } return &vap->iv_nw_keys[vap->iv_def_txkey]; } return &ni->ni_ucastkey; }
void ieee80211_notify_replay_failure(struct ieee80211vap *vap, const struct ieee80211_frame *wh, const struct ieee80211_key *k, u_int64_t rsc, int tid) { struct ifnet *ifp = vap->iv_ifp; IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2, "%s replay detected tid %d <rsc %ju, csc %ju, keyix %u rxkeyix %u>", k->wk_cipher->ic_name, tid, (intmax_t) rsc, (intmax_t) k->wk_keyrsc[tid], k->wk_keyix, k->wk_rxkeyix); if (ifp != NULL) { /* NB: for cipher test modules */ struct ieee80211_replay_event iev; IEEE80211_ADDR_COPY(iev.iev_dst, wh->i_addr1); IEEE80211_ADDR_COPY(iev.iev_src, wh->i_addr2); iev.iev_cipher = k->wk_cipher->ic_cipher; if (k->wk_rxkeyix != IEEE80211_KEYIX_NONE) iev.iev_keyix = k->wk_rxkeyix; else iev.iev_keyix = k->wk_keyix; iev.iev_keyrsc = k->wk_keyrsc[tid]; iev.iev_rsc = rsc; CURVNET_SET(ifp->if_vnet); rt_ieee80211msg(ifp, RTM_IEEE80211_REPLAY, &iev, sizeof(iev)); CURVNET_RESTORE(); } }
/* * Add privacy headers appropriate for the specified key. */ struct ieee80211_key * ieee80211_crypto_encap(struct ieee80211_node *ni, struct sk_buff *skb) { struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_key *k; struct ieee80211_frame *wh; const struct ieee80211_cipher *cip; u_int8_t keyid; /* * Multicast traffic always uses the multicast key. * Otherwise if a unicast key is set we use that and * it is always key index 0. When no unicast key is * set we fall back to the default transmit key. */ wh = (struct ieee80211_frame *)skb->data; if (IEEE80211_IS_MULTICAST(wh->i_addr1) || ni->ni_ucastkey.wk_cipher == &ieee80211_cipher_none) { if (vap->iv_def_txkey == IEEE80211_KEYIX_NONE) { IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr1, "no default transmit key (%s) deftxkey %u", __func__, vap->iv_def_txkey); vap->iv_stats.is_tx_nodefkey++; return NULL; } keyid = vap->iv_def_txkey; k = &vap->iv_nw_keys[vap->iv_def_txkey]; } else { keyid = 0; k = &ni->ni_ucastkey; } cip = k->wk_cipher; if (skb_headroom(skb) < cip->ic_header) { /* * Should not happen; ieee80211_skbhdr_adjust should * have allocated enough space for all headers. */ IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr1, "%s: malformed packet for cipher %s; headroom %u", __func__, cip->ic_name, skb_headroom(skb)); vap->iv_stats.is_tx_noheadroom++; return NULL; } return (cip->ic_encap(k, skb, keyid << 6) ? k : NULL); }
/* * Mark a scan cache entry after a successful associate. */ void ieee80211_scan_assoc_success(struct ieee80211vap *vap, const uint8_t mac[]) { struct ieee80211_scan_state *ss = vap->iv_ic->ic_scan; if (ss->ss_ops != NULL) { IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_SCAN, mac, "%s", __func__); ss->ss_ops->scan_assoc_success(ss, mac); } }
/* * Add privacy headers and do any s/w encryption required. */ static int tkip_encap(struct ieee80211_key *k, struct mbuf *m, uint8_t keyid) { struct tkip_ctx *ctx = k->wk_private; struct ieee80211vap *vap = ctx->tc_vap; struct ieee80211com *ic = vap->iv_ic; uint8_t *ivp; int hdrlen; /* * Handle TKIP counter measures requirement. */ if (vap->iv_flags & IEEE80211_F_COUNTERM) { #ifdef IEEE80211_DEBUG struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *); #endif IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2, "discard frame due to countermeasures (%s)", __func__); vap->iv_stats.is_crypto_tkipcm++; return 0; } hdrlen = ieee80211_hdrspace(ic, mtod(m, void *)); /* * Copy down 802.11 header and add the IV, KeyID, and ExtIV. */ M_PREPEND(m, tkip.ic_header, M_NOWAIT); if (m == NULL) return 0; ivp = mtod(m, uint8_t *); memmove(ivp, ivp + tkip.ic_header, hdrlen); ivp += hdrlen; ivp[0] = k->wk_keytsc >> 8; /* TSC1 */ ivp[1] = (ivp[0] | 0x20) & 0x7f; /* WEP seed */ ivp[2] = k->wk_keytsc >> 0; /* TSC0 */ ivp[3] = keyid | IEEE80211_WEP_EXTIV; /* KeyID | ExtID */ ivp[4] = k->wk_keytsc >> 16; /* TSC2 */ ivp[5] = k->wk_keytsc >> 24; /* TSC3 */ ivp[6] = k->wk_keytsc >> 32; /* TSC4 */ ivp[7] = k->wk_keytsc >> 40; /* TSC5 */ #if 0 if (hdrlen == 24) { M_PREPEND(m, tkip.ic_miclen + 12, M_NOWAIT); if (m == NULL) return 0; ivp = mtod(m, uint8_t *); memmove(ivp, ivp + tkip.ic_miclen + 12, hdrlen + tkip.ic_header); ivp += hdrlen + tkip.ic_header; bzero(ivp, 20); memcpy((ivp+12), k->wk_txmic, tkip.ic_header); }
/* * Demerit a scan cache entry after failing to associate. */ void ieee80211_scan_assoc_fail(struct ieee80211vap *vap, const uint8_t mac[], int reason) { struct ieee80211_scan_state *ss = vap->iv_ic->ic_scan; if (ss->ss_ops != NULL) { IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_SCAN, mac, "%s: reason %u", __func__, reason); ss->ss_ops->scan_assoc_fail(ss, mac, reason); } }
static int none_encap(struct ieee80211_key *k, struct mbuf *m) { struct ieee80211vap *vap = k->wk_private; #ifdef IEEE80211_DEBUG struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *); #endif uint8_t keyid; keyid = ieee80211_crypto_get_keyid(vap, k); /* * The specified key is not setup; this can * happen, at least, when changing keys. */ IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr1, "key id %u is not set (encap)", keyid); vap->iv_stats.is_tx_badcipher++; return 0; }
void ieee80211_notify_michael_failure(struct ieee80211vap *vap, const struct ieee80211_frame *wh, u_int keyix) { struct ifnet *ifp = vap->iv_ifp; IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2, "michael MIC verification failed <keyix %u>", keyix); vap->iv_stats.is_rx_tkipmic++; if (ifp != NULL) { /* NB: for cipher test modules */ struct ieee80211_michael_event iev; IEEE80211_ADDR_COPY(iev.iev_dst, wh->i_addr1); IEEE80211_ADDR_COPY(iev.iev_src, wh->i_addr2); iev.iev_cipher = IEEE80211_CIPHER_TKIP; iev.iev_keyix = keyix; CURVNET_SET(ifp->if_vnet); rt_ieee80211msg(ifp, RTM_IEEE80211_MICHAEL, &iev, sizeof(iev)); CURVNET_RESTORE(); } }
/*zhaoyang1 add start for interfere ap*/ wbuf_t autelan_beacon_alloc(struct ieee80211_node *ni, struct ieee80211_beacon_offsets *bo, u_int8_t *ap_mac, u_int8_t chan) { struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; wbuf_t wbuf; struct ieee80211_frame *wh; u_int8_t *frm; wbuf = wbuf_alloc(ic->ic_osdev, WBUF_TX_BEACON, MAX_TX_RX_PACKET_SIZE); if (wbuf == NULL) return NULL; wh = (struct ieee80211_frame *)wbuf_header(wbuf); wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_BEACON; wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; *(u_int16_t *)wh->i_dur = 0; IEEE80211_ADDR_COPY(wh->i_addr1, IEEE80211_GET_BCAST_ADDR(ic)); IEEE80211_ADDR_COPY(wh->i_addr2, ap_mac); IEEE80211_ADDR_COPY(wh->i_addr3, ap_mac); *(u_int16_t *)wh->i_seq = 0; frm = (u_int8_t *)&wh[1]; frm = autelan_beacon_init(ni, bo, frm, chan); if (ieee80211_vap_copy_beacon_is_set(vap)) { store_beacon_frame(vap, (u_int8_t *)wh, (frm - (u_int8_t *)wh)); } wbuf_set_pktlen(wbuf, (frm - (u_int8_t *) wbuf_header(wbuf))); wbuf_set_node(wbuf, ieee80211_ref_node(ni)); IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MLME, vap->iv_myaddr, "%s \n", __func__); return wbuf; }
static struct ieee80211_node * hwmp_discover(struct ieee80211vap *vap, const uint8_t dest[IEEE80211_ADDR_LEN], struct mbuf *m) { struct ieee80211_hwmp_state *hs = vap->iv_hwmp; struct ieee80211_mesh_state *ms = vap->iv_mesh; struct ieee80211_mesh_route *rt = NULL; struct ieee80211_hwmp_route *hr; struct ieee80211_meshpreq_ie preq; struct ieee80211_node *ni; int sendpreq = 0; #ifdef IEEE80211_DEBUG char ethstr[ETHER_ADDRSTRLEN + 1]; #endif KASSERT(vap->iv_opmode == IEEE80211_M_MBSS, ("not a mesh vap, opmode %d", vap->iv_opmode)); KASSERT(!IEEE80211_ADDR_EQ(vap->iv_myaddr, dest), ("%s: discovering self!", __func__)); ni = NULL; if (!IEEE80211_IS_MULTICAST(dest)) { rt = ieee80211_mesh_rt_find(vap, dest); if (rt == NULL) { rt = ieee80211_mesh_rt_add(vap, dest); if (rt == NULL) { IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, "unable to add discovery path to %s", kether_ntoa(dest, ethstr)); vap->iv_stats.is_mesh_rtaddfailed++; goto done; } } hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) { if (hr->hr_origseq == 0) hr->hr_origseq = ++hs->hs_seq; rt->rt_metric = IEEE80211_MESHLMETRIC_INITIALVAL; rt->rt_lifetime = ticks_to_msecs(ieee80211_hwmp_pathtimeout); /* XXX check preq retries */ sendpreq = 1; if (m != NULL) { IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP, dest, "%s", "start path discovery (src <none>)"); } else { IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP, dest, "start path discovery (src %s)", kether_ntoa( mtod(m, struct ether_header *)->ether_shost, ethstr)); } /* * Try to discover the path for this node. */ preq.preq_flags = 0; preq.preq_hopcount = 0; preq.preq_ttl = ms->ms_ttl; preq.preq_id = ++hs->hs_preqid; IEEE80211_ADDR_COPY(preq.preq_origaddr, vap->iv_myaddr); preq.preq_origseq = hr->hr_origseq; preq.preq_lifetime = rt->rt_lifetime; preq.preq_metric = rt->rt_metric; preq.preq_tcount = 1; IEEE80211_ADDR_COPY(PREQ_TADDR(0), dest); PREQ_TFLAGS(0) = 0; if (ieee80211_hwmp_targetonly) PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_TO; if (ieee80211_hwmp_replyforward) PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_RF; PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_USN; PREQ_TSEQ(0) = 0; /* XXX check return value */ hwmp_send_preq(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &preq); } if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) ni = ieee80211_find_txnode(vap, rt->rt_nexthop); } else {
void mlme_recv_auth_btamp(struct ieee80211_node *ni, u_int16_t algo, u_int16_t seq, u_int16_t status_code, u_int8_t *challenge, u_int8_t challenge_length, wbuf_t wbuf) { struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_mlme_priv *mlme_priv = vap->iv_mlme_priv; struct ieee80211_frame *wh; u_int16_t indication_status = IEEE80211_STATUS_SUCCESS,response_status = IEEE80211_STATUS_SUCCESS ; bool send_auth_response=true, indicate=true; wh = (struct ieee80211_frame *) wbuf_header(wbuf); /* AP must be up and running */ if (!mlme_priv->im_connection_up || ieee80211_vap_ready_is_clear(vap)) { return; } IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_AUTH, wh->i_addr2, "recv auth frame with algorithm %d seq %d \n", algo, seq); do { /* Check node existance for the peer */ if (ni == vap->iv_bss) { return; } else { ieee80211_ref_node(ni); } /* Validate algo */ if (algo == IEEE80211_AUTH_ALG_OPEN) { if (mlme_priv->im_expected_auth_seq_number) { send_auth_response = false; indicate = false; if (seq == mlme_priv->im_expected_auth_seq_number) { if (!OS_CANCEL_TIMER(&mlme_priv->im_timeout_timer)) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_MLME, "%s: Timed-out already\n", __func__); break; } IEEE80211_DPRINTF(vap, IEEE80211_MSG_MLME, "%s: mlme_auth_complete\n", __func__); /* Request complete */ mlme_priv->im_request_type = MLME_REQ_NONE; /* Authentication complete (success or failure) */ IEEE80211_DELIVER_EVENT_MLME_AUTH_COMPLETE(vap, status_code); vap->iv_mlme_priv->im_expected_auth_seq_number = 0; } else { break; } } else { if (seq != IEEE80211_AUTH_OPEN_REQUEST) { response_status = IEEE80211_STATUS_SEQUENCE; indication_status = IEEE80211_STATUS_SEQUENCE; break; } else { indicate = true; send_auth_response = true; } } } else if (algo == IEEE80211_AUTH_ALG_SHARED) { response_status = IEEE80211_STATUS_ALG; indication_status = IEEE80211_STATUS_ALG; break; } else { IEEE80211_DPRINTF(vap, IEEE80211_MSG_AUTH | IEEE80211_MSG_CRYPTO, "[%s] auth: unsupported algorithm %d \n",ether_sprintf(wh->i_addr2),algo); vap->iv_stats.is_rx_auth_unsupported++; response_status = IEEE80211_STATUS_ALG; indication_status = IEEE80211_STATUS_ALG; break; } } while (FALSE); IEEE80211_DELIVER_EVENT_MLME_AUTH_INDICATION(vap, ni->ni_macaddr, indication_status); if (send_auth_response) { ieee80211_send_auth(ni, seq + 1, response_status, NULL, 0); } if (ni) { if (indication_status != IEEE80211_STATUS_SUCCESS ){ /* auth is not success, remove the node from node table*/ ieee80211_node_leave(ni); } /* * release the reference created at the begining of the case above * either by alloc_node or ref_node. */ ieee80211_free_node(ni); } }
/* * Validate and strip privacy headers (and trailer) for a * received frame. The specified key should be correct but * is also verified. */ static int ccmp_decap(struct ieee80211_key *k, wbuf_t wbuf, int hdrlen, struct ieee80211_rx_status *rs) { struct ccmp_ctx *ctx = k->wk_private; struct ieee80211vap *vap = ctx->cc_vap; struct ieee80211_frame *wh; uint8_t *ivp, *origHdr; u_int64_t pn; u_int8_t tid; struct ieee80211_mac_stats *mac_stats; u_int32_t hwmfp; uint8_t update_keyrsc = 1; /* * Header should have extended IV and sequence number; * verify the former and validate the latter. */ origHdr = (u_int8_t *)wbuf_header(wbuf); wh = (struct ieee80211_frame *)origHdr; mac_stats = IEEE80211_IS_MULTICAST(wh->i_addr1) ? &vap->iv_multicast_stats : &vap->iv_unicast_stats; if (IEEE80211_IS_MFP_FRAME(wh)) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, "%s MFP frame\n", __func__); } if (rs->rs_flags & IEEE80211_RX_DECRYPT_ERROR) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, "%s decrypt error\n", __func__); if (IEEE80211_IS_MFP_FRAME(wh)) { /* It may not be real crypto error, but hardware didn't do correct * decryption. Try software decrypt later. */ rs->rs_flags &= ~IEEE80211_RX_DECRYPT_ERROR; rs->rs_flags |= IEEE80211_RX_MIC_ERROR; } else { /* The frame already failed decryption in hardware, * just update statistics and return. */ mac_stats->ims_rx_ccmpmic++; return 0; } } ivp = origHdr + hdrlen; if ((ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV) == 0) { /* * No extended IV; discard frame. */ IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2, "%s", "Missing ExtIV for AES-CCM cipher"); mac_stats->ims_rx_ccmpformat++; return 0; } tid = IEEE80211_NON_QOS_SEQ; if (IEEE80211_QOS_HAS_SEQ(wh)) { if ( (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS ) { tid = ((struct ieee80211_qosframe_addr4 *)wh)->i_qos[0] & IEEE80211_QOS_TID; } else { tid = ((struct ieee80211_qosframe *)wh)->i_qos[0] & IEEE80211_QOS_TID; } } /* NB: assume IEEEE80211_WEP_MINLEN covers the extended IV */ pn = READ_6(ivp[0], ivp[1], ivp[4], ivp[5], ivp[6], ivp[7]); if (pn <= k->wk_keyrsc[tid]) { /* * Replay violation. */ IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO, "%s: CCMP Replay! Throw away. new pn=0x%x%x, " "current pn=0x%x%x. seq=0x%x,Rsvd=0x%x,keyID=0x%x,tid=%d\n", __func__, (u_int32_t)(pn>>32), (u_int32_t)pn, (u_int32_t)(k->wk_keyrsc[tid] >> 32), (u_int32_t)k->wk_keyrsc[tid], *(u_int16_t*)(wh->i_seq), ivp[2], ivp[3], tid ); ieee80211_notify_replay_failure(vap, wh, k, pn); mac_stats->ims_rx_ccmpreplay++; return 0; }