/* * Handle a station joining an RSN network. */ void ieee80211_node_join_rsn(struct ieee80211com *ic, struct ieee80211_node *ni) { DPRINTF(("station %s associated using proto %d akm 0x%x " "cipher 0x%x groupcipher 0x%x\n", ether_sprintf(ni->ni_macaddr), ni->ni_rsnprotos, ni->ni_rsnakms, ni->ni_rsnciphers, ni->ni_rsngroupcipher)); ni->ni_rsn_state = RSNA_AUTHENTICATION; ic->ic_rsnsta++; ni->ni_key_count = 0; ni->ni_port_valid = 0; ni->ni_flags &= ~IEEE80211_NODE_TXRXPROT; ni->ni_replaycnt = -1; /* XXX */ ni->ni_rsn_retries = 0; ni->ni_rsncipher = ni->ni_rsnciphers; ni->ni_rsn_state = RSNA_AUTHENTICATION_2; /* generate a new authenticator nonce (ANonce) */ arc4random_buf(ni->ni_nonce, EAPOL_KEY_NONCE_LEN); if (!ieee80211_is_8021x_akm(ni->ni_rsnakms)) { memcpy(ni->ni_pmk, ic->ic_psk, IEEE80211_PMK_LEN); ni->ni_flags |= IEEE80211_NODE_PMK; (void)ieee80211_send_4way_msg1(ic, ni); } else if (ni->ni_flags & IEEE80211_NODE_PMK) { /* skip 802.1X auth if a cached PMK was found */ (void)ieee80211_send_4way_msg1(ic, ni); } else { /* no cached PMK found, needs full 802.1X auth */ ieee80211_needs_auth(ic, ni); } }
/* * 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); }