LCOV - code coverage report
Current view: top level - net80211 - ieee80211_pae_output.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 304 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 13 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: ieee80211_pae_output.c,v 1.30 2017/12/21 12:09:38 mpi Exp $   */
       2             : 
       3             : /*-
       4             :  * Copyright (c) 2007,2008 Damien Bergamini <damien.bergamini@free.fr>
       5             :  *
       6             :  * Permission to use, copy, modify, and distribute this software for any
       7             :  * purpose with or without fee is hereby granted, provided that the above
       8             :  * copyright notice and this permission notice appear in all copies.
       9             :  *
      10             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      11             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      12             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      13             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      14             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      15             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      16             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      17             :  */
      18             : 
      19             : /*
      20             :  * This code implements the 4-Way Handshake and Group Key Handshake protocols
      21             :  * (both Supplicant and Authenticator Key Transmit state machines) defined in
      22             :  * IEEE Std 802.11-2007 section 8.5.
      23             :  */
      24             : 
      25             : #include <sys/param.h>
      26             : #include <sys/systm.h>
      27             : #include <sys/mbuf.h>
      28             : #include <sys/kernel.h>
      29             : #include <sys/socket.h>
      30             : #include <sys/sockio.h>
      31             : #include <sys/endian.h>
      32             : #include <sys/errno.h>
      33             : 
      34             : #include <net/if.h>
      35             : #include <net/if_dl.h>
      36             : #include <net/if_media.h>
      37             : #include <net/if_llc.h>
      38             : 
      39             : #include <netinet/in.h>
      40             : #include <netinet/if_ether.h>
      41             : #include <netinet/ip.h>
      42             : 
      43             : #include <net80211/ieee80211_var.h>
      44             : #include <net80211/ieee80211_priv.h>
      45             : 
      46             : int             ieee80211_send_eapol_key(struct ieee80211com *, struct mbuf *,
      47             :                     struct ieee80211_node *, const struct ieee80211_ptk *);
      48             : #ifndef IEEE80211_STA_ONLY
      49             : u_int8_t        *ieee80211_add_gtk_kde(u_int8_t *, struct ieee80211_node *,
      50             :                     const struct ieee80211_key *);
      51             : u_int8_t        *ieee80211_add_pmkid_kde(u_int8_t *, const u_int8_t *);
      52             : u_int8_t        *ieee80211_add_igtk_kde(u_int8_t *,
      53             :                     const struct ieee80211_key *);
      54             : #endif
      55             : struct mbuf     *ieee80211_get_eapol_key(int, int, u_int);
      56             : 
      57             : /*
      58             :  * Send an EAPOL-Key frame to node `ni'.  If MIC or encryption is required,
      59             :  * the PTK must be passed (otherwise it can be set to NULL.)
      60             :  */
      61             : int
      62           0 : ieee80211_send_eapol_key(struct ieee80211com *ic, struct mbuf *m,
      63             :     struct ieee80211_node *ni, const struct ieee80211_ptk *ptk)
      64             : {
      65           0 :         struct ifnet *ifp = &ic->ic_if;
      66             :         struct ether_header *eh;
      67             :         struct ieee80211_eapol_key *key;
      68             :         u_int16_t info;
      69             :         int len, error;
      70             : 
      71           0 :         M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT);
      72           0 :         if (m == NULL)
      73           0 :                 return ENOMEM;
      74             :         /* no need to m_pullup here (ok by construction) */
      75           0 :         eh = mtod(m, struct ether_header *);
      76           0 :         eh->ether_type = htons(ETHERTYPE_PAE);
      77           0 :         IEEE80211_ADDR_COPY(eh->ether_shost, ic->ic_myaddr);
      78           0 :         IEEE80211_ADDR_COPY(eh->ether_dhost, ni->ni_macaddr);
      79             : 
      80           0 :         key = (struct ieee80211_eapol_key *)&eh[1];
      81           0 :         key->version = EAPOL_VERSION;
      82           0 :         key->type = EAPOL_KEY;
      83           0 :         key->desc = (ni->ni_rsnprotos == IEEE80211_PROTO_RSN) ?
      84             :             EAPOL_KEY_DESC_IEEE80211 : EAPOL_KEY_DESC_WPA;
      85             : 
      86           0 :         info = BE_READ_2(key->info);
      87             :         /* use V3 descriptor if KDF is SHA256-based */
      88           0 :         if (ieee80211_is_sha256_akm(ni->ni_rsnakms))
      89           0 :                 info |= EAPOL_KEY_DESC_V3;
      90             :         /* use V2 descriptor if pairwise or group cipher is CCMP */
      91           0 :         else if (ni->ni_rsncipher == IEEE80211_CIPHER_CCMP ||
      92           0 :             ni->ni_rsngroupcipher == IEEE80211_CIPHER_CCMP)
      93           0 :                 info |= EAPOL_KEY_DESC_V2;
      94             :         else
      95           0 :                 info |= EAPOL_KEY_DESC_V1;
      96           0 :         BE_WRITE_2(key->info, info);
      97             : 
      98           0 :         len = m->m_len - sizeof(struct ether_header);
      99           0 :         BE_WRITE_2(key->paylen, len - sizeof(*key));
     100           0 :         BE_WRITE_2(key->len, len - 4);
     101             : 
     102             : #ifndef IEEE80211_STA_ONLY
     103           0 :         if (info & EAPOL_KEY_ENCRYPTED) {
     104           0 :                 if (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) {
     105             :                         /* clear "Encrypted" bit for WPA */
     106           0 :                         info &= ~EAPOL_KEY_ENCRYPTED;
     107           0 :                         BE_WRITE_2(key->info, info);
     108           0 :                 }
     109           0 :                 ieee80211_eapol_key_encrypt(ic, key, ptk->kek);
     110             : 
     111           0 :                 if ((info & EAPOL_KEY_VERSION_MASK) != EAPOL_KEY_DESC_V1) {
     112             :                         /* AES Key Wrap adds 8 bytes + padding */
     113           0 :                         m->m_pkthdr.len = m->m_len =
     114           0 :                             sizeof(*eh) + 4 + BE_READ_2(key->len);
     115           0 :                 }
     116             :         }
     117             : #endif
     118           0 :         if (info & EAPOL_KEY_KEYMIC)
     119           0 :                 ieee80211_eapol_key_mic(key, ptk->kck);
     120             : 
     121             : #ifndef IEEE80211_STA_ONLY
     122             :         /* start a 100ms timeout if an answer is expected from supplicant */
     123           0 :         if (info & EAPOL_KEY_KEYACK)
     124           0 :                 timeout_add_msec(&ni->ni_eapol_to, 100);
     125             : #endif
     126             : 
     127           0 :         IFQ_ENQUEUE(&ifp->if_snd, m, error);
     128           0 :         if (error)
     129           0 :                 return (error);
     130           0 :         if_start(ifp);
     131           0 :         return 0;
     132           0 : }
     133             : 
     134             : #ifndef IEEE80211_STA_ONLY
     135             : /*
     136             :  * Handle EAPOL-Key timeouts (no answer from supplicant).
     137             :  */
     138             : void
     139           0 : ieee80211_eapol_timeout(void *arg)
     140             : {
     141           0 :         struct ieee80211_node *ni = arg;
     142           0 :         struct ieee80211com *ic = ni->ni_ic;
     143             :         int s;
     144             : 
     145             :         DPRINTF(("no answer from station %s in state %d\n",
     146             :             ether_sprintf(ni->ni_macaddr), ni->ni_rsn_state));
     147             : 
     148           0 :         s = splnet();
     149             : 
     150           0 :         switch (ni->ni_rsn_state) {
     151             :         case RSNA_PTKSTART:
     152             :         case RSNA_PTKCALCNEGOTIATING:
     153           0 :                 (void)ieee80211_send_4way_msg1(ic, ni);
     154           0 :                 break;
     155             :         case RSNA_PTKINITNEGOTIATING:
     156           0 :                 (void)ieee80211_send_4way_msg3(ic, ni);
     157           0 :                 break;
     158             :         }
     159             : 
     160           0 :         switch (ni->ni_rsn_gstate) {
     161             :         case RSNA_REKEYNEGOTIATING:
     162           0 :                 (void)ieee80211_send_group_msg1(ic, ni);
     163           0 :                 break;
     164             :         }
     165             : 
     166           0 :         splx(s);
     167           0 : }
     168             : 
     169             : /*
     170             :  * Add a GTK KDE to an EAPOL-Key frame (see Figure 144).
     171             :  */
     172             : u_int8_t *
     173           0 : ieee80211_add_gtk_kde(u_int8_t *frm, struct ieee80211_node *ni,
     174             :     const struct ieee80211_key *k)
     175             : {
     176           0 :         KASSERT(k->k_flags & IEEE80211_KEY_GROUP);
     177             : 
     178           0 :         *frm++ = IEEE80211_ELEMID_VENDOR;
     179           0 :         *frm++ = 6 + k->k_len;
     180           0 :         memcpy(frm, IEEE80211_OUI, 3); frm += 3;
     181           0 :         *frm++ = IEEE80211_KDE_GTK;
     182           0 :         *frm = k->k_id & 3;
     183             :         /*
     184             :          * The TxRx flag for sending a GTK is always the opposite of whether
     185             :          * the pairwise key is used for data encryption/integrity or not.
     186             :          */
     187           0 :         if (ni->ni_rsncipher == IEEE80211_CIPHER_USEGROUP)
     188           0 :                 *frm |= 1 << 2;   /* set the Tx bit */
     189           0 :         frm++;
     190           0 :         *frm++ = 0;     /* reserved */
     191           0 :         memcpy(frm, k->k_key, k->k_len);
     192           0 :         return frm + k->k_len;
     193             : }
     194             : 
     195             : /*
     196             :  * Add a PMKID KDE to an EAPOL-Key frame (see Figure 146).
     197             :  */
     198             : u_int8_t *
     199           0 : ieee80211_add_pmkid_kde(u_int8_t *frm, const u_int8_t *pmkid)
     200             : {
     201           0 :         *frm++ = IEEE80211_ELEMID_VENDOR;
     202           0 :         *frm++ = 20;
     203           0 :         memcpy(frm, IEEE80211_OUI, 3); frm += 3;
     204           0 :         *frm++ = IEEE80211_KDE_PMKID;
     205           0 :         memcpy(frm, pmkid, IEEE80211_PMKID_LEN);
     206           0 :         return frm + IEEE80211_PMKID_LEN;
     207             : }
     208             : 
     209             : /*
     210             :  * Add an IGTK KDE to an EAPOL-Key frame (see Figure 8-32a).
     211             :  */
     212             : u_int8_t *
     213           0 : ieee80211_add_igtk_kde(u_int8_t *frm, const struct ieee80211_key *k)
     214             : {
     215           0 :         KASSERT(k->k_flags & IEEE80211_KEY_IGTK);
     216             : 
     217           0 :         *frm++ = IEEE80211_ELEMID_VENDOR;
     218           0 :         *frm++ = 4 + 24;
     219           0 :         memcpy(frm, IEEE80211_OUI, 3); frm += 3;
     220           0 :         *frm++ = IEEE80211_KDE_IGTK;
     221           0 :         LE_WRITE_2(frm, k->k_id); frm += 2;
     222           0 :         LE_WRITE_6(frm, k->k_tsc); frm += 6; /* IPN */
     223           0 :         memcpy(frm, k->k_key, 16);
     224           0 :         return frm + 16;
     225             : }
     226             : #endif  /* IEEE80211_STA_ONLY */
     227             : 
     228             : struct mbuf *
     229           0 : ieee80211_get_eapol_key(int flags, int type, u_int pktlen)
     230             : {
     231             :         struct mbuf *m;
     232             : 
     233             :         /* reserve space for 802.11 encapsulation and EAPOL-Key header */
     234           0 :         pktlen += sizeof(struct ieee80211_frame) + LLC_SNAPFRAMELEN +
     235             :             sizeof(struct ieee80211_eapol_key);
     236             : 
     237           0 :         if (pktlen > MCLBYTES)
     238           0 :                 panic("EAPOL-Key frame too large: %u", pktlen);
     239           0 :         MGETHDR(m, flags, type);
     240           0 :         if (m == NULL)
     241           0 :                 return NULL;
     242           0 :         if (pktlen > MHLEN) {
     243           0 :                 MCLGET(m, flags);
     244           0 :                 if (!(m->m_flags & M_EXT))
     245           0 :                         return m_free(m);
     246             :         }
     247           0 :         m->m_data += sizeof(struct ieee80211_frame) + LLC_SNAPFRAMELEN;
     248           0 :         return m;
     249           0 : }
     250             : 
     251             : #ifndef IEEE80211_STA_ONLY
     252             : /*
     253             :  * Send 4-Way Handshake Message 1 to the supplicant.
     254             :  */
     255             : int
     256           0 : ieee80211_send_4way_msg1(struct ieee80211com *ic, struct ieee80211_node *ni)
     257             : {
     258             :         struct ieee80211_eapol_key *key;
     259             :         struct mbuf *m;
     260             :         u_int16_t info, keylen;
     261             :         u_int8_t *frm;
     262             : 
     263           0 :         ni->ni_rsn_state = RSNA_PTKSTART;
     264           0 :         if (++ni->ni_rsn_retries > 3) {
     265           0 :                 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
     266             :                     IEEE80211_REASON_4WAY_TIMEOUT);
     267           0 :                 ieee80211_node_leave(ic, ni);
     268           0 :                 return 0;
     269             :         }
     270           0 :         m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA,
     271           0 :             (ni->ni_rsnprotos == IEEE80211_PROTO_RSN) ? 2 + 20 : 0);
     272           0 :         if (m == NULL)
     273           0 :                 return ENOMEM;
     274           0 :         key = mtod(m, struct ieee80211_eapol_key *);
     275           0 :         memset(key, 0, sizeof(*key));
     276             : 
     277             :         info = EAPOL_KEY_PAIRWISE | EAPOL_KEY_KEYACK;
     278           0 :         BE_WRITE_2(key->info, info);
     279             : 
     280             :         /* copy the authenticator's nonce (ANonce) */
     281           0 :         memcpy(key->nonce, ni->ni_nonce, EAPOL_KEY_NONCE_LEN);
     282             : 
     283           0 :         keylen = ieee80211_cipher_keylen(ni->ni_rsncipher);
     284           0 :         BE_WRITE_2(key->keylen, keylen);
     285             : 
     286           0 :         frm = (u_int8_t *)&key[1];
     287             :         /* NB: WPA does not have PMKID KDE */
     288           0 :         if (ni->ni_rsnprotos == IEEE80211_PROTO_RSN &&
     289           0 :             ieee80211_is_8021x_akm(ni->ni_rsnakms))
     290           0 :                 frm = ieee80211_add_pmkid_kde(frm, ni->ni_pmkid);
     291             : 
     292           0 :         m->m_pkthdr.len = m->m_len = frm - (u_int8_t *)key;
     293             : 
     294           0 :         if (ic->ic_if.if_flags & IFF_DEBUG)
     295           0 :                 printf("%s: sending msg %d/%d of the %s handshake to %s\n",
     296           0 :                     ic->ic_if.if_xname, 1, 4, "4-way",
     297           0 :                     ether_sprintf(ni->ni_macaddr));
     298             : 
     299           0 :         ni->ni_replaycnt++;
     300           0 :         BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);
     301             : 
     302           0 :         return ieee80211_send_eapol_key(ic, m, ni, NULL);
     303           0 : }
     304             : #endif  /* IEEE80211_STA_ONLY */
     305             : 
     306             : /*
     307             :  * Send 4-Way Handshake Message 2 to the authenticator.
     308             :  */
     309             : int
     310           0 : ieee80211_send_4way_msg2(struct ieee80211com *ic, struct ieee80211_node *ni,
     311             :     const u_int8_t *replaycnt, const struct ieee80211_ptk *tptk)
     312             : {
     313             :         struct ieee80211_eapol_key *key;
     314             :         struct mbuf *m;
     315             :         u_int16_t info;
     316             :         u_int8_t *frm;
     317             : 
     318           0 :         ni->ni_rsn_supp_state = RSNA_SUPP_PTKNEGOTIATING;
     319           0 :         m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA,
     320           0 :             (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) ?
     321             :                 2 + IEEE80211_WPAIE_MAXLEN :
     322             :                 2 + IEEE80211_RSNIE_MAXLEN);
     323           0 :         if (m == NULL)
     324           0 :                 return ENOMEM;
     325           0 :         key = mtod(m, struct ieee80211_eapol_key *);
     326           0 :         memset(key, 0, sizeof(*key));
     327             : 
     328             :         info = EAPOL_KEY_PAIRWISE | EAPOL_KEY_KEYMIC;
     329           0 :         BE_WRITE_2(key->info, info);
     330             : 
     331             :         /* copy key replay counter from Message 1/4 */
     332           0 :         memcpy(key->replaycnt, replaycnt, 8);
     333             : 
     334             :         /* copy the supplicant's nonce (SNonce) */
     335           0 :         memcpy(key->nonce, ic->ic_nonce, EAPOL_KEY_NONCE_LEN);
     336             : 
     337           0 :         frm = (u_int8_t *)&key[1];
     338             :         /* add the WPA/RSN IE used in the (Re)Association Request */
     339           0 :         if (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) {
     340             :                 int keylen;
     341           0 :                 frm = ieee80211_add_wpa(frm, ic, ni);
     342             :                 /* WPA sets the key length field here */
     343           0 :                 keylen = ieee80211_cipher_keylen(ni->ni_rsncipher);
     344           0 :                 BE_WRITE_2(key->keylen, keylen);
     345           0 :         } else  /* RSN */
     346           0 :                 frm = ieee80211_add_rsn(frm, ic, ni);
     347             : 
     348           0 :         m->m_pkthdr.len = m->m_len = frm - (u_int8_t *)key;
     349             : 
     350           0 :         if (ic->ic_if.if_flags & IFF_DEBUG)
     351           0 :                 printf("%s: sending msg %d/%d of the %s handshake to %s\n",
     352           0 :                     ic->ic_if.if_xname, 2, 4, "4-way",
     353           0 :                     ether_sprintf(ni->ni_macaddr));
     354             : 
     355           0 :         return ieee80211_send_eapol_key(ic, m, ni, tptk);
     356           0 : }
     357             : 
     358             : #ifndef IEEE80211_STA_ONLY
     359             : /*
     360             :  * Send 4-Way Handshake Message 3 to the supplicant.
     361             :  */
     362             : int
     363           0 : ieee80211_send_4way_msg3(struct ieee80211com *ic, struct ieee80211_node *ni)
     364             : {
     365             :         struct ieee80211_eapol_key *key;
     366             :         struct ieee80211_key *k = NULL;
     367             :         struct mbuf *m;
     368             :         u_int16_t info, keylen;
     369             :         u_int8_t *frm;
     370             : 
     371           0 :         ni->ni_rsn_state = RSNA_PTKINITNEGOTIATING;
     372           0 :         if (++ni->ni_rsn_retries > 3) {
     373           0 :                 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
     374             :                     IEEE80211_REASON_4WAY_TIMEOUT);
     375           0 :                 ieee80211_node_leave(ic, ni);
     376           0 :                 return 0;
     377             :         }
     378           0 :         if (ni->ni_rsnprotos == IEEE80211_PROTO_RSN) {
     379           0 :                 k = &ic->ic_nw_keys[ic->ic_def_txkey];
     380           0 :                 m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA,
     381           0 :                     2 + IEEE80211_RSNIE_MAXLEN + 2 + 6 + k->k_len + 15 +
     382           0 :                     ((ni->ni_flags & IEEE80211_NODE_MFP) ? 2 + 28 : 0));
     383           0 :         } else { /* WPA */
     384           0 :                 m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA,
     385           0 :                     2 + IEEE80211_WPAIE_MAXLEN +
     386           0 :                     ((ni->ni_flags & IEEE80211_NODE_MFP) ? 2 + 28 : 0));
     387             :         }
     388           0 :         if (m == NULL)
     389           0 :                 return ENOMEM;
     390           0 :         key = mtod(m, struct ieee80211_eapol_key *);
     391           0 :         memset(key, 0, sizeof(*key));
     392             : 
     393             :         info = EAPOL_KEY_PAIRWISE | EAPOL_KEY_KEYACK | EAPOL_KEY_KEYMIC;
     394           0 :         if (ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP)
     395           0 :                 info |= EAPOL_KEY_INSTALL;
     396             : 
     397             :         /* use same nonce as in Message 1 */
     398           0 :         memcpy(key->nonce, ni->ni_nonce, EAPOL_KEY_NONCE_LEN);
     399             : 
     400           0 :         ni->ni_replaycnt++;
     401           0 :         BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);
     402             : 
     403           0 :         keylen = ieee80211_cipher_keylen(ni->ni_rsncipher);
     404           0 :         BE_WRITE_2(key->keylen, keylen);
     405             : 
     406           0 :         frm = (u_int8_t *)&key[1];
     407             :         /* add the WPA/RSN IE included in Beacon/Probe Response */
     408           0 :         if (ni->ni_rsnprotos == IEEE80211_PROTO_RSN) {
     409           0 :                 frm = ieee80211_add_rsn(frm, ic, ic->ic_bss);
     410             :                 /* encapsulate the GTK */
     411           0 :                 frm = ieee80211_add_gtk_kde(frm, ni, k);
     412           0 :                 LE_WRITE_6(key->rsc, k->k_tsc);
     413             :                 /* encapsulate the IGTK if MFP was negotiated */
     414           0 :                 if (ni->ni_flags & IEEE80211_NODE_MFP) {
     415           0 :                         frm = ieee80211_add_igtk_kde(frm,
     416           0 :                             &ic->ic_nw_keys[ic->ic_igtk_kid]);
     417           0 :                 }
     418             :                 /* ask that the EAPOL-Key frame be encrypted */
     419           0 :                 info |= EAPOL_KEY_ENCRYPTED | EAPOL_KEY_SECURE;
     420           0 :         } else  /* WPA */
     421           0 :                 frm = ieee80211_add_wpa(frm, ic, ic->ic_bss);
     422             : 
     423             :         /* write the key info field */
     424           0 :         BE_WRITE_2(key->info, info);
     425             : 
     426           0 :         m->m_pkthdr.len = m->m_len = frm - (u_int8_t *)key;
     427             : 
     428           0 :         if (ic->ic_if.if_flags & IFF_DEBUG)
     429           0 :                 printf("%s: sending msg %d/%d of the %s handshake to %s\n",
     430           0 :                     ic->ic_if.if_xname, 3, 4, "4-way",
     431           0 :                     ether_sprintf(ni->ni_macaddr));
     432             : 
     433           0 :         return ieee80211_send_eapol_key(ic, m, ni, &ni->ni_ptk);
     434           0 : }
     435             : #endif  /* IEEE80211_STA_ONLY */
     436             : 
     437             : /*
     438             :  * Send 4-Way Handshake Message 4 to the authenticator.
     439             :  */
     440             : int
     441           0 : ieee80211_send_4way_msg4(struct ieee80211com *ic, struct ieee80211_node *ni)
     442             : {
     443             :         struct ieee80211_eapol_key *key;
     444             :         struct mbuf *m;
     445             :         u_int16_t info;
     446             : 
     447           0 :         ni->ni_rsn_supp_state = RNSA_SUPP_PTKDONE;
     448           0 :         m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA, 0);
     449           0 :         if (m == NULL)
     450           0 :                 return ENOMEM;
     451           0 :         key = mtod(m, struct ieee80211_eapol_key *);
     452           0 :         memset(key, 0, sizeof(*key));
     453             : 
     454             :         info = EAPOL_KEY_PAIRWISE | EAPOL_KEY_KEYMIC;
     455             : 
     456             :         /* copy key replay counter from authenticator */
     457           0 :         BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);
     458             : 
     459           0 :         if (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) {
     460             :                 int keylen;
     461             :                 /* WPA sets the key length field here */
     462           0 :                 keylen = ieee80211_cipher_keylen(ni->ni_rsncipher);
     463           0 :                 BE_WRITE_2(key->keylen, keylen);
     464           0 :         } else
     465             :                 info |= EAPOL_KEY_SECURE;
     466             : 
     467             :         /* write the key info field */
     468           0 :         BE_WRITE_2(key->info, info);
     469             : 
     470             :         /* empty key data field */
     471           0 :         m->m_pkthdr.len = m->m_len = sizeof(*key);
     472             : 
     473           0 :         if (ic->ic_if.if_flags & IFF_DEBUG)
     474           0 :                 printf("%s: sending msg %d/%d of the %s handshake to %s\n",
     475           0 :                     ic->ic_if.if_xname, 4, 4, "4-way",
     476           0 :                     ether_sprintf(ni->ni_macaddr));
     477             : 
     478           0 :         return ieee80211_send_eapol_key(ic, m, ni, &ni->ni_ptk);
     479           0 : }
     480             : 
     481             : #ifndef IEEE80211_STA_ONLY
     482             : /*
     483             :  * Send Group Key Handshake Message 1 to the supplicant.
     484             :  */
     485             : int
     486           0 : ieee80211_send_group_msg1(struct ieee80211com *ic, struct ieee80211_node *ni)
     487             : {
     488             :         struct ieee80211_eapol_key *key;
     489             :         const struct ieee80211_key *k;
     490             :         struct mbuf *m;
     491             :         u_int16_t info;
     492             :         u_int8_t *frm;
     493             :         u_int8_t kid;
     494             : 
     495           0 :         ni->ni_rsn_gstate = RSNA_REKEYNEGOTIATING;
     496           0 :         if (++ni->ni_rsn_retries > 3) {
     497           0 :                 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
     498             :                     IEEE80211_REASON_GROUP_TIMEOUT);
     499           0 :                 ieee80211_node_leave(ic, ni);
     500           0 :                 return 0;
     501             :         }
     502           0 :         if (ni->ni_flags & IEEE80211_NODE_REKEY)
     503           0 :                 kid = (ic->ic_def_txkey == 1) ? 2 : 1;
     504             :         else
     505           0 :                 kid = ic->ic_def_txkey;
     506           0 :         k = &ic->ic_nw_keys[kid];
     507             : 
     508           0 :         m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA,
     509           0 :             ((ni->ni_rsnprotos == IEEE80211_PROTO_WPA) ?
     510           0 :                 k->k_len : 2 + 6 + k->k_len) +
     511           0 :             ((ni->ni_flags & IEEE80211_NODE_MFP) ? 2 + 28 : 0) +
     512             :             15);
     513           0 :         if (m == NULL)
     514           0 :                 return ENOMEM;
     515           0 :         key = mtod(m, struct ieee80211_eapol_key *);
     516           0 :         memset(key, 0, sizeof(*key));
     517             : 
     518             :         info = EAPOL_KEY_KEYACK | EAPOL_KEY_KEYMIC | EAPOL_KEY_SECURE |
     519             :             EAPOL_KEY_ENCRYPTED;
     520             : 
     521           0 :         ni->ni_replaycnt++;
     522           0 :         BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);
     523             : 
     524           0 :         frm = (u_int8_t *)&key[1];
     525           0 :         if (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) {
     526             :                 /* WPA does not have GTK KDE */
     527           0 :                 BE_WRITE_2(key->keylen, k->k_len);
     528           0 :                 memcpy(frm, k->k_key, k->k_len);
     529           0 :                 frm += k->k_len;
     530           0 :                 info |= (k->k_id & 0x3) << EAPOL_KEY_WPA_KID_SHIFT;
     531           0 :                 if (ni->ni_rsncipher == IEEE80211_CIPHER_USEGROUP)
     532           0 :                         info |= EAPOL_KEY_WPA_TX;
     533             :         } else {        /* RSN */
     534           0 :                 frm = ieee80211_add_gtk_kde(frm, ni, k);
     535           0 :                 if (ni->ni_flags & IEEE80211_NODE_MFP) {
     536           0 :                         if (ni->ni_flags & IEEE80211_NODE_REKEY)
     537           0 :                                 kid = (ic->ic_igtk_kid == 4) ? 5 : 4;
     538             :                         else
     539           0 :                                 kid = ic->ic_igtk_kid;
     540           0 :                         frm = ieee80211_add_igtk_kde(frm,
     541           0 :                             &ic->ic_nw_keys[kid]);
     542           0 :                 }
     543             :         }
     544             :         /* RSC = last transmit sequence number for the GTK */
     545           0 :         LE_WRITE_6(key->rsc, k->k_tsc);
     546             : 
     547             :         /* write the key info field */
     548           0 :         BE_WRITE_2(key->info, info);
     549             : 
     550           0 :         m->m_pkthdr.len = m->m_len = frm - (u_int8_t *)key;
     551             : 
     552           0 :         if (ic->ic_if.if_flags & IFF_DEBUG)
     553           0 :                 printf("%s: sending msg %d/%d of the %s handshake to %s\n",
     554           0 :                     ic->ic_if.if_xname, 1, 2, "group key",
     555           0 :                     ether_sprintf(ni->ni_macaddr));
     556             : 
     557           0 :         return ieee80211_send_eapol_key(ic, m, ni, &ni->ni_ptk);
     558           0 : }
     559             : #endif  /* IEEE80211_STA_ONLY */
     560             : 
     561             : /*
     562             :  * Send Group Key Handshake Message 2 to the authenticator.
     563             :  */
     564             : int
     565           0 : ieee80211_send_group_msg2(struct ieee80211com *ic, struct ieee80211_node *ni,
     566             :     const struct ieee80211_key *k)
     567             : {
     568             :         struct ieee80211_eapol_key *key;
     569             :         u_int16_t info;
     570             :         struct mbuf *m;
     571             : 
     572           0 :         m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA, 0);
     573           0 :         if (m == NULL)
     574           0 :                 return ENOMEM;
     575           0 :         key = mtod(m, struct ieee80211_eapol_key *);
     576           0 :         memset(key, 0, sizeof(*key));
     577             : 
     578             :         info = EAPOL_KEY_KEYMIC | EAPOL_KEY_SECURE;
     579             : 
     580             :         /* copy key replay counter from authenticator */
     581           0 :         BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);
     582             : 
     583           0 :         if (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) {
     584             :                 /* WPA sets the key length and key id fields here */
     585           0 :                 BE_WRITE_2(key->keylen, k->k_len);
     586           0 :                 info |= (k->k_id & 3) << EAPOL_KEY_WPA_KID_SHIFT;
     587           0 :         }
     588             : 
     589             :         /* write the key info field */
     590           0 :         BE_WRITE_2(key->info, info);
     591             : 
     592             :         /* empty key data field */
     593           0 :         m->m_pkthdr.len = m->m_len = sizeof(*key);
     594             : 
     595           0 :         if (ic->ic_if.if_flags & IFF_DEBUG)
     596           0 :                 printf("%s: sending msg %d/%d of the %s handshake to %s\n",
     597           0 :                     ic->ic_if.if_xname, 2, 2, "group key",
     598           0 :                     ether_sprintf(ni->ni_macaddr));
     599             : 
     600           0 :         return ieee80211_send_eapol_key(ic, m, ni, &ni->ni_ptk);
     601           0 : }
     602             : 
     603             : /*
     604             :  * EAPOL-Key Request frames are sent by the supplicant to request that the
     605             :  * authenticator initiates either a 4-Way Handshake or Group Key Handshake,
     606             :  * or to report a MIC failure in a TKIP MSDU.
     607             :  */
     608             : int
     609           0 : ieee80211_send_eapol_key_req(struct ieee80211com *ic,
     610             :     struct ieee80211_node *ni, u_int16_t info, u_int64_t tsc)
     611             : {
     612             :         struct ieee80211_eapol_key *key;
     613             :         struct mbuf *m;
     614             : 
     615           0 :         m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA, 0);
     616           0 :         if (m == NULL)
     617           0 :                 return ENOMEM;
     618           0 :         key = mtod(m, struct ieee80211_eapol_key *);
     619           0 :         memset(key, 0, sizeof(*key));
     620             : 
     621           0 :         info |= EAPOL_KEY_REQUEST;
     622           0 :         BE_WRITE_2(key->info, info);
     623             : 
     624             :         /* in case of TKIP MIC failure, fill the RSC field */
     625           0 :         if (info & EAPOL_KEY_ERROR)
     626           0 :                 LE_WRITE_6(key->rsc, tsc);
     627             : 
     628             :         /* use our separate key replay counter for key requests */
     629           0 :         BE_WRITE_8(key->replaycnt, ni->ni_reqreplaycnt);
     630           0 :         ni->ni_reqreplaycnt++;
     631             : 
     632             :         /* empty key data field */
     633           0 :         m->m_pkthdr.len = m->m_len = sizeof(*key);
     634             : 
     635           0 :         if (ic->ic_if.if_flags & IFF_DEBUG)
     636           0 :                 printf("%s: sending EAPOL-Key request to %s\n",
     637           0 :                     ic->ic_if.if_xname, ether_sprintf(ni->ni_macaddr));
     638             : 
     639           0 :         return ieee80211_send_eapol_key(ic, m, ni, &ni->ni_ptk);
     640           0 : }

Generated by: LCOV version 1.13