/* * Send 4-Way Handshake Message 1 to the supplicant. */ int ieee80211_send_4way_msg1(struct ieee80211com *ic, struct ieee80211_node *ni) { struct ieee80211_eapol_key *key; struct mbuf *m; u_int16_t info, keylen; u_int8_t *frm; ni->ni_rsn_state = RSNA_PTKSTART; if (++ni->ni_rsn_retries > 3) { IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH, IEEE80211_REASON_4WAY_TIMEOUT); ieee80211_node_leave(ic, ni); return 0; } m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA, (ni->ni_rsnprotos == IEEE80211_PROTO_RSN) ? 2 + 20 : 0); if (m == NULL) return ENOMEM; key = mtod(m, struct ieee80211_eapol_key *); memset(key, 0, sizeof(*key)); info = EAPOL_KEY_PAIRWISE | EAPOL_KEY_KEYACK; BE_WRITE_2(key->info, info); /* copy the authenticator's nonce (ANonce) */ memcpy(key->nonce, ni->ni_nonce, EAPOL_KEY_NONCE_LEN); keylen = ieee80211_cipher_keylen(ni->ni_rsncipher); BE_WRITE_2(key->keylen, keylen); frm = (u_int8_t *)&key[1]; /* NB: WPA does not have PMKID KDE */ if (ni->ni_rsnprotos == IEEE80211_PROTO_RSN && ieee80211_is_8021x_akm(ni->ni_rsnakms)) frm = ieee80211_add_pmkid_kde(frm, ni->ni_pmkid); m->m_pkthdr.len = m->m_len = frm - (u_int8_t *)key; if (ic->ic_if.if_flags & IFF_DEBUG) printf("%s: sending msg %d/%d of the %s handshake to %s\n", ic->ic_if.if_xname, 1, 4, "4-way", ether_sprintf(ni->ni_macaddr)); ni->ni_replaycnt++; BE_WRITE_8(key->replaycnt, ni->ni_replaycnt); return ieee80211_send_eapol_key(ic, m, ni, NULL); }
/* * Send 4-Way Handshake Message 2 to the authenticator. */ int ieee80211_send_4way_msg2(struct ieee80211com *ic, struct ieee80211_node *ni, const u_int8_t *replaycnt, const struct ieee80211_ptk *tptk) { struct ieee80211_eapol_key *key; struct mbuf *m; u_int16_t info; u_int8_t *frm; m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA, (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) ? 2 + IEEE80211_WPAIE_MAXLEN : 2 + IEEE80211_RSNIE_MAXLEN); if (m == NULL) return ENOMEM; key = mtod(m, struct ieee80211_eapol_key *); memset(key, 0, sizeof(*key)); info = EAPOL_KEY_PAIRWISE | EAPOL_KEY_KEYMIC; BE_WRITE_2(key->info, info); /* copy key replay counter from Message 1/4 */ memcpy(key->replaycnt, replaycnt, 8); /* copy the supplicant's nonce (SNonce) */ memcpy(key->nonce, ic->ic_nonce, EAPOL_KEY_NONCE_LEN); frm = (u_int8_t *)&key[1]; /* add the WPA/RSN IE used in the (Re)Association Request */ if (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) { int keylen; frm = ieee80211_add_wpa(frm, ic, ni); /* WPA sets the key length field here */ keylen = ieee80211_cipher_keylen(ni->ni_rsncipher); BE_WRITE_2(key->keylen, keylen); } else /* RSN */ frm = ieee80211_add_rsn(frm, ic, ni); m->m_pkthdr.len = m->m_len = frm - (u_int8_t *)key; if (ic->ic_if.if_flags & IFF_DEBUG) printf("%s: sending msg %d/%d of the %s handshake to %s\n", ic->ic_if.if_xname, 2, 4, "4-way", ether_sprintf(ni->ni_macaddr)); return ieee80211_send_eapol_key(ic, m, ni, tptk); }
/* * Send 4-Way Handshake Message 4 to the authenticator. */ int ieee80211_send_4way_msg4(struct ieee80211com *ic, struct ieee80211_node *ni) { struct ieee80211_eapol_key *key; struct mbuf *m; u_int16_t info; m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA, 0); if (m == NULL) return ENOMEM; key = mtod(m, struct ieee80211_eapol_key *); memset(key, 0, sizeof(*key)); info = EAPOL_KEY_PAIRWISE | EAPOL_KEY_KEYMIC; /* copy key replay counter from authenticator */ BE_WRITE_8(key->replaycnt, ni->ni_replaycnt); if (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) { int keylen; /* WPA sets the key length field here */ keylen = ieee80211_cipher_keylen(ni->ni_rsncipher); BE_WRITE_2(key->keylen, keylen); } else info |= EAPOL_KEY_SECURE; /* write the key info field */ BE_WRITE_2(key->info, info); /* empty key data field */ m->m_pkthdr.len = m->m_len = sizeof(*key); if (ic->ic_if.if_flags & IFF_DEBUG) printf("%s: sending msg %d/%d of the %s handshake to %s\n", ic->ic_if.if_xname, 4, 4, "4-way", ether_sprintf(ni->ni_macaddr)); return ieee80211_send_eapol_key(ic, m, ni, &ni->ni_ptk); }
/* * Send 4-Way Handshake Message 3 to the supplicant. */ int ieee80211_send_4way_msg3(struct ieee80211com *ic, struct ieee80211_node *ni) { struct ieee80211_eapol_key *key; struct ieee80211_key *k = NULL; struct mbuf *m; u_int16_t info, keylen; u_int8_t *frm; ni->ni_rsn_state = RSNA_PTKINITNEGOTIATING; if (++ni->ni_rsn_retries > 3) { IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH, IEEE80211_REASON_4WAY_TIMEOUT); ieee80211_node_leave(ic, ni); return 0; } if (ni->ni_rsnprotos == IEEE80211_PROTO_RSN) { k = &ic->ic_nw_keys[ic->ic_def_txkey]; m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA, 2 + IEEE80211_RSNIE_MAXLEN + 2 + 6 + k->k_len + 15 + ((ni->ni_flags & IEEE80211_NODE_MFP) ? 2 + 28 : 0)); } else { /* WPA */ m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA, 2 + IEEE80211_WPAIE_MAXLEN + ((ni->ni_flags & IEEE80211_NODE_MFP) ? 2 + 28 : 0)); } if (m == NULL) return ENOMEM; key = mtod(m, struct ieee80211_eapol_key *); memset(key, 0, sizeof(*key)); info = EAPOL_KEY_PAIRWISE | EAPOL_KEY_KEYACK | EAPOL_KEY_KEYMIC; if (ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP) info |= EAPOL_KEY_INSTALL; /* use same nonce as in Message 1 */ memcpy(key->nonce, ni->ni_nonce, EAPOL_KEY_NONCE_LEN); ni->ni_replaycnt++; BE_WRITE_8(key->replaycnt, ni->ni_replaycnt); keylen = ieee80211_cipher_keylen(ni->ni_rsncipher); BE_WRITE_2(key->keylen, keylen); frm = (u_int8_t *)&key[1]; /* add the WPA/RSN IE included in Beacon/Probe Response */ if (ni->ni_rsnprotos == IEEE80211_PROTO_RSN) { frm = ieee80211_add_rsn(frm, ic, ic->ic_bss); /* encapsulate the GTK */ frm = ieee80211_add_gtk_kde(frm, ni, k); LE_WRITE_6(key->rsc, k->k_tsc); /* encapsulate the IGTK if MFP was negotiated */ if (ni->ni_flags & IEEE80211_NODE_MFP) { frm = ieee80211_add_igtk_kde(frm, &ic->ic_nw_keys[ic->ic_igtk_kid]); } /* ask that the EAPOL-Key frame be encrypted */ info |= EAPOL_KEY_ENCRYPTED | EAPOL_KEY_SECURE; } else /* WPA */ frm = ieee80211_add_wpa(frm, ic, ic->ic_bss); /* write the key info field */ BE_WRITE_2(key->info, info); m->m_pkthdr.len = m->m_len = frm - (u_int8_t *)key; if (ic->ic_if.if_flags & IFF_DEBUG) printf("%s: sending msg %d/%d of the %s handshake to %s\n", ic->ic_if.if_xname, 3, 4, "4-way", ether_sprintf(ni->ni_macaddr)); return ieee80211_send_eapol_key(ic, m, ni, &ni->ni_ptk); }
void ieee80211_create_ibss(struct ieee80211com* ic, struct ieee80211_channel *chan) { struct ieee80211_node *ni; struct ifnet *ifp = &ic->ic_if; ni = ic->ic_bss; if (ifp->if_flags & IFF_DEBUG) printf("%s: creating ibss\n", ifp->if_xname); ic->ic_flags |= IEEE80211_F_SIBSS; ni->ni_chan = chan; ni->ni_rates = ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)]; ni->ni_txrate = 0; IEEE80211_ADDR_COPY(ni->ni_macaddr, ic->ic_myaddr); IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_myaddr); if (ic->ic_opmode == IEEE80211_M_IBSS) { if ((ic->ic_flags & IEEE80211_F_DESBSSID) != 0) IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_des_bssid); else ni->ni_bssid[0] |= 0x02; /* local bit for IBSS */ } ni->ni_esslen = ic->ic_des_esslen; memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen); ni->ni_rssi = 0; ni->ni_rstamp = 0; memset(ni->ni_tstamp, 0, sizeof(ni->ni_tstamp)); ni->ni_intval = ic->ic_lintval; ni->ni_capinfo = IEEE80211_CAPINFO_IBSS; if (ic->ic_flags & IEEE80211_F_WEPON) ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY; if (ic->ic_flags & IEEE80211_F_RSNON) { struct ieee80211_key *k; /* initialize 256-bit global key counter to a random value */ arc4random_buf(ic->ic_globalcnt, EAPOL_KEY_NONCE_LEN); ni->ni_rsnprotos = ic->ic_rsnprotos; ni->ni_rsnakms = ic->ic_rsnakms; ni->ni_rsnciphers = ic->ic_rsnciphers; ni->ni_rsngroupcipher = ic->ic_rsngroupcipher; ni->ni_rsngroupmgmtcipher = ic->ic_rsngroupmgmtcipher; ni->ni_rsncaps = 0; if (ic->ic_caps & IEEE80211_C_MFP) { ni->ni_rsncaps |= IEEE80211_RSNCAP_MFPC; if (ic->ic_flags & IEEE80211_F_MFPR) ni->ni_rsncaps |= IEEE80211_RSNCAP_MFPR; } ic->ic_def_txkey = 1; k = &ic->ic_nw_keys[ic->ic_def_txkey]; memset(k, 0, sizeof(*k)); k->k_id = ic->ic_def_txkey; k->k_cipher = ni->ni_rsngroupcipher; k->k_flags = IEEE80211_KEY_GROUP | IEEE80211_KEY_TX; k->k_len = ieee80211_cipher_keylen(k->k_cipher); arc4random_buf(k->k_key, k->k_len); (*ic->ic_set_key)(ic, ni, k); /* XXX */ if (ic->ic_caps & IEEE80211_C_MFP) { ic->ic_igtk_kid = 4; k = &ic->ic_nw_keys[ic->ic_igtk_kid]; memset(k, 0, sizeof(*k)); k->k_id = ic->ic_igtk_kid; k->k_cipher = ni->ni_rsngroupmgmtcipher; k->k_flags = IEEE80211_KEY_IGTK | IEEE80211_KEY_TX; k->k_len = 16; arc4random_buf(k->k_key, k->k_len); (*ic->ic_set_key)(ic, ni, k); /* XXX */ } /* * In HostAP mode, multicast traffic is sent using ic_bss * as the Tx node, so mark our node as valid so we can send * multicast frames using the group key we've just configured. */ ni->ni_port_valid = 1; ni->ni_flags |= IEEE80211_NODE_TXPROT; /* schedule a GTK/IGTK rekeying after 3600s */ timeout_add_sec(&ic->ic_rsn_timeout, 3600); } timeout_add_sec(&ic->ic_inact_timeout, IEEE80211_INACT_WAIT); timeout_add_sec(&ic->ic_node_cache_timeout, IEEE80211_CACHE_WAIT); ieee80211_new_state(ic, IEEE80211_S_RUN, -1); }