The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net80211/ieee80211_pae_output.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: ieee80211_pae_output.c,v 1.33 2022/01/05 05:18:25 dlg 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 ieee80211_send_eapol_key(struct ieee80211com *ic, struct mbuf *m,
   63     struct ieee80211_node *ni, const struct ieee80211_ptk *ptk)
   64 {
   65         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         M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT);
   72         if (m == NULL)
   73                 return ENOMEM;
   74         /* no need to m_pullup here (ok by construction) */
   75         eh = mtod(m, struct ether_header *);
   76         eh->ether_type = htons(ETHERTYPE_EAPOL);
   77         IEEE80211_ADDR_COPY(eh->ether_shost, ic->ic_myaddr);
   78         IEEE80211_ADDR_COPY(eh->ether_dhost, ni->ni_macaddr);
   79 
   80         key = (struct ieee80211_eapol_key *)&eh[1];
   81         key->version = EAPOL_VERSION;
   82         key->type = EAPOL_KEY;
   83         key->desc = (ni->ni_rsnprotos == IEEE80211_PROTO_RSN) ?
   84             EAPOL_KEY_DESC_IEEE80211 : EAPOL_KEY_DESC_WPA;
   85 
   86         info = BE_READ_2(key->info);
   87         /* use V3 descriptor if KDF is SHA256-based */
   88         if (ieee80211_is_sha256_akm(ni->ni_rsnakms))
   89                 info |= EAPOL_KEY_DESC_V3;
   90         /* use V2 descriptor if pairwise or group cipher is CCMP */
   91         else if (ni->ni_rsncipher == IEEE80211_CIPHER_CCMP ||
   92             ni->ni_rsngroupcipher == IEEE80211_CIPHER_CCMP)
   93                 info |= EAPOL_KEY_DESC_V2;
   94         else
   95                 info |= EAPOL_KEY_DESC_V1;
   96         BE_WRITE_2(key->info, info);
   97 
   98         len = m->m_len - sizeof(struct ether_header);
   99         BE_WRITE_2(key->paylen, len - sizeof(*key));
  100         BE_WRITE_2(key->len, len - 4);
  101 
  102 #ifndef IEEE80211_STA_ONLY
  103         if (info & EAPOL_KEY_ENCRYPTED) {
  104                 if (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) {
  105                         /* clear "Encrypted" bit for WPA */
  106                         info &= ~EAPOL_KEY_ENCRYPTED;
  107                         BE_WRITE_2(key->info, info);
  108                 }
  109                 ieee80211_eapol_key_encrypt(ic, key, ptk->kek);
  110 
  111                 if ((info & EAPOL_KEY_VERSION_MASK) != EAPOL_KEY_DESC_V1) {
  112                         /* AES Key Wrap adds 8 bytes + padding */
  113                         m->m_pkthdr.len = m->m_len =
  114                             sizeof(*eh) + 4 + BE_READ_2(key->len);
  115                 }
  116         }
  117 #endif
  118         if (info & EAPOL_KEY_KEYMIC)
  119                 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         if (info & EAPOL_KEY_KEYACK)
  124                 timeout_add_msec(&ni->ni_eapol_to, 100);
  125 #endif
  126 
  127         error = ifq_enqueue(&ifp->if_snd, m);
  128         if (error)
  129                 return (error);
  130         if_start(ifp);
  131         return 0;
  132 }
  133 
  134 #ifndef IEEE80211_STA_ONLY
  135 /*
  136  * Handle EAPOL-Key timeouts (no answer from supplicant).
  137  */
  138 void
  139 ieee80211_eapol_timeout(void *arg)
  140 {
  141         struct ieee80211_node *ni = arg;
  142         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         s = splnet();
  149 
  150         switch (ni->ni_rsn_state) {
  151         case RSNA_PTKSTART:
  152         case RSNA_PTKCALCNEGOTIATING:
  153                 (void)ieee80211_send_4way_msg1(ic, ni);
  154                 break;
  155         case RSNA_PTKINITNEGOTIATING:
  156                 (void)ieee80211_send_4way_msg3(ic, ni);
  157                 break;
  158         }
  159 
  160         switch (ni->ni_rsn_gstate) {
  161         case RSNA_REKEYNEGOTIATING:
  162                 (void)ieee80211_send_group_msg1(ic, ni);
  163                 break;
  164         }
  165 
  166         splx(s);
  167 }
  168 
  169 /*
  170  * Add a GTK KDE to an EAPOL-Key frame (see Figure 144).
  171  */
  172 u_int8_t *
  173 ieee80211_add_gtk_kde(u_int8_t *frm, struct ieee80211_node *ni,
  174     const struct ieee80211_key *k)
  175 {
  176         KASSERT(k->k_flags & IEEE80211_KEY_GROUP);
  177 
  178         *frm++ = IEEE80211_ELEMID_VENDOR;
  179         *frm++ = 6 + k->k_len;
  180         memcpy(frm, IEEE80211_OUI, 3); frm += 3;
  181         *frm++ = IEEE80211_KDE_GTK;
  182         *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         if (ni->ni_rsncipher == IEEE80211_CIPHER_USEGROUP)
  188                 *frm |= 1 << 2; /* set the Tx bit */
  189         frm++;
  190         *frm++ = 0;     /* reserved */
  191         memcpy(frm, k->k_key, k->k_len);
  192         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 ieee80211_add_pmkid_kde(u_int8_t *frm, const u_int8_t *pmkid)
  200 {
  201         *frm++ = IEEE80211_ELEMID_VENDOR;
  202         *frm++ = 20;
  203         memcpy(frm, IEEE80211_OUI, 3); frm += 3;
  204         *frm++ = IEEE80211_KDE_PMKID;
  205         memcpy(frm, pmkid, IEEE80211_PMKID_LEN);
  206         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 ieee80211_add_igtk_kde(u_int8_t *frm, const struct ieee80211_key *k)
  214 {
  215         KASSERT(k->k_flags & IEEE80211_KEY_IGTK);
  216 
  217         *frm++ = IEEE80211_ELEMID_VENDOR;
  218         *frm++ = 4 + 24;
  219         memcpy(frm, IEEE80211_OUI, 3); frm += 3;
  220         *frm++ = IEEE80211_KDE_IGTK;
  221         LE_WRITE_2(frm, k->k_id); frm += 2;
  222         LE_WRITE_6(frm, k->k_tsc); frm += 6;    /* IPN */
  223         memcpy(frm, k->k_key, 16);
  224         return frm + 16;
  225 }
  226 #endif  /* IEEE80211_STA_ONLY */
  227 
  228 struct mbuf *
  229 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         pktlen += sizeof(struct ieee80211_frame) + LLC_SNAPFRAMELEN +
  235             sizeof(struct ieee80211_eapol_key);
  236 
  237         if (pktlen > MCLBYTES)
  238                 panic("EAPOL-Key frame too large: %u", pktlen);
  239         MGETHDR(m, flags, type);
  240         if (m == NULL)
  241                 return NULL;
  242         if (pktlen > MHLEN) {
  243                 MCLGET(m, flags);
  244                 if (!(m->m_flags & M_EXT))
  245                         return m_free(m);
  246         }
  247         m->m_data += sizeof(struct ieee80211_frame) + LLC_SNAPFRAMELEN;
  248         return m;
  249 }
  250 
  251 #ifndef IEEE80211_STA_ONLY
  252 /*
  253  * Send 4-Way Handshake Message 1 to the supplicant.
  254  */
  255 int
  256 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         ni->ni_rsn_state = RSNA_PTKSTART;
  264         if (++ni->ni_rsn_retries > 3) {
  265                 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
  266                     IEEE80211_REASON_4WAY_TIMEOUT);
  267                 ieee80211_node_leave(ic, ni);
  268                 return 0;
  269         }
  270         m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA,
  271             (ni->ni_rsnprotos == IEEE80211_PROTO_RSN) ? 2 + 20 : 0);
  272         if (m == NULL)
  273                 return ENOMEM;
  274         key = mtod(m, struct ieee80211_eapol_key *);
  275         memset(key, 0, sizeof(*key));
  276 
  277         info = EAPOL_KEY_PAIRWISE | EAPOL_KEY_KEYACK;
  278         BE_WRITE_2(key->info, info);
  279 
  280         /* copy the authenticator's nonce (ANonce) */
  281         memcpy(key->nonce, ni->ni_nonce, EAPOL_KEY_NONCE_LEN);
  282 
  283         keylen = ieee80211_cipher_keylen(ni->ni_rsncipher);
  284         BE_WRITE_2(key->keylen, keylen);
  285 
  286         frm = (u_int8_t *)&key[1];
  287         /* NB: WPA does not have PMKID KDE */
  288         if (ni->ni_rsnprotos == IEEE80211_PROTO_RSN &&
  289             ieee80211_is_8021x_akm(ni->ni_rsnakms))
  290                 frm = ieee80211_add_pmkid_kde(frm, ni->ni_pmkid);
  291 
  292         m->m_pkthdr.len = m->m_len = frm - (u_int8_t *)key;
  293 
  294         if (ic->ic_if.if_flags & IFF_DEBUG)
  295                 printf("%s: sending msg %d/%d of the %s handshake to %s\n",
  296                     ic->ic_if.if_xname, 1, 4, "4-way",
  297                     ether_sprintf(ni->ni_macaddr));
  298 
  299         ni->ni_replaycnt++;
  300         BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);
  301 
  302         return ieee80211_send_eapol_key(ic, m, ni, NULL);
  303 }
  304 #endif  /* IEEE80211_STA_ONLY */
  305 
  306 /*
  307  * Send 4-Way Handshake Message 2 to the authenticator.
  308  */
  309 int
  310 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         ni->ni_rsn_supp_state = RSNA_SUPP_PTKNEGOTIATING;
  319         m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA,
  320             (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) ?
  321                 2 + IEEE80211_WPAIE_MAXLEN :
  322                 2 + IEEE80211_RSNIE_MAXLEN);
  323         if (m == NULL)
  324                 return ENOMEM;
  325         key = mtod(m, struct ieee80211_eapol_key *);
  326         memset(key, 0, sizeof(*key));
  327 
  328         info = EAPOL_KEY_PAIRWISE | EAPOL_KEY_KEYMIC;
  329         BE_WRITE_2(key->info, info);
  330 
  331         /* copy key replay counter from Message 1/4 */
  332         memcpy(key->replaycnt, replaycnt, 8);
  333 
  334         /* copy the supplicant's nonce (SNonce) */
  335         memcpy(key->nonce, ic->ic_nonce, EAPOL_KEY_NONCE_LEN);
  336 
  337         frm = (u_int8_t *)&key[1];
  338         /* add the WPA/RSN IE used in the (Re)Association Request */
  339         if (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) {
  340                 int keylen;
  341                 frm = ieee80211_add_wpa(frm, ic, ni);
  342                 /* WPA sets the key length field here */
  343                 keylen = ieee80211_cipher_keylen(ni->ni_rsncipher);
  344                 BE_WRITE_2(key->keylen, keylen);
  345         } else  /* RSN */
  346                 frm = ieee80211_add_rsn(frm, ic, ni);
  347 
  348         m->m_pkthdr.len = m->m_len = frm - (u_int8_t *)key;
  349 
  350         if (ic->ic_if.if_flags & IFF_DEBUG)
  351                 printf("%s: sending msg %d/%d of the %s handshake to %s\n",
  352                     ic->ic_if.if_xname, 2, 4, "4-way",
  353                     ether_sprintf(ni->ni_macaddr));
  354 
  355         return ieee80211_send_eapol_key(ic, m, ni, tptk);
  356 }
  357 
  358 #ifndef IEEE80211_STA_ONLY
  359 /*
  360  * Send 4-Way Handshake Message 3 to the supplicant.
  361  */
  362 int
  363 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         ni->ni_rsn_state = RSNA_PTKINITNEGOTIATING;
  372         if (++ni->ni_rsn_retries > 3) {
  373                 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
  374                     IEEE80211_REASON_4WAY_TIMEOUT);
  375                 ieee80211_node_leave(ic, ni);
  376                 return 0;
  377         }
  378         if (ni->ni_rsnprotos == IEEE80211_PROTO_RSN) {
  379                 k = &ic->ic_nw_keys[ic->ic_def_txkey];
  380                 m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA,
  381                     2 + IEEE80211_RSNIE_MAXLEN + 2 + 6 + k->k_len + 15 +
  382                     ((ni->ni_flags & IEEE80211_NODE_MFP) ? 2 + 28 : 0));
  383         } else { /* WPA */
  384                 m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA,
  385                     2 + IEEE80211_WPAIE_MAXLEN +
  386                     ((ni->ni_flags & IEEE80211_NODE_MFP) ? 2 + 28 : 0));
  387         }
  388         if (m == NULL)
  389                 return ENOMEM;
  390         key = mtod(m, struct ieee80211_eapol_key *);
  391         memset(key, 0, sizeof(*key));
  392 
  393         info = EAPOL_KEY_PAIRWISE | EAPOL_KEY_KEYACK | EAPOL_KEY_KEYMIC;
  394         if (ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP)
  395                 info |= EAPOL_KEY_INSTALL;
  396 
  397         /* use same nonce as in Message 1 */
  398         memcpy(key->nonce, ni->ni_nonce, EAPOL_KEY_NONCE_LEN);
  399 
  400         ni->ni_replaycnt++;
  401         BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);
  402 
  403         keylen = ieee80211_cipher_keylen(ni->ni_rsncipher);
  404         BE_WRITE_2(key->keylen, keylen);
  405 
  406         frm = (u_int8_t *)&key[1];
  407         /* add the WPA/RSN IE included in Beacon/Probe Response */
  408         if (ni->ni_rsnprotos == IEEE80211_PROTO_RSN) {
  409                 frm = ieee80211_add_rsn(frm, ic, ic->ic_bss);
  410                 /* encapsulate the GTK */
  411                 frm = ieee80211_add_gtk_kde(frm, ni, k);
  412                 LE_WRITE_6(key->rsc, k->k_tsc);
  413                 /* encapsulate the IGTK if MFP was negotiated */
  414                 if (ni->ni_flags & IEEE80211_NODE_MFP) {
  415                         frm = ieee80211_add_igtk_kde(frm,
  416                             &ic->ic_nw_keys[ic->ic_igtk_kid]);
  417                 }
  418                 /* ask that the EAPOL-Key frame be encrypted */
  419                 info |= EAPOL_KEY_ENCRYPTED | EAPOL_KEY_SECURE;
  420         } else  /* WPA */
  421                 frm = ieee80211_add_wpa(frm, ic, ic->ic_bss);
  422 
  423         /* write the key info field */
  424         BE_WRITE_2(key->info, info);
  425 
  426         m->m_pkthdr.len = m->m_len = frm - (u_int8_t *)key;
  427 
  428         if (ic->ic_if.if_flags & IFF_DEBUG)
  429                 printf("%s: sending msg %d/%d of the %s handshake to %s\n",
  430                     ic->ic_if.if_xname, 3, 4, "4-way",
  431                     ether_sprintf(ni->ni_macaddr));
  432 
  433         return ieee80211_send_eapol_key(ic, m, ni, &ni->ni_ptk);
  434 }
  435 #endif  /* IEEE80211_STA_ONLY */
  436 
  437 /*
  438  * Send 4-Way Handshake Message 4 to the authenticator.
  439  */
  440 int
  441 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         ni->ni_rsn_supp_state = RSNA_SUPP_PTKDONE;
  448         m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA, 0);
  449         if (m == NULL)
  450                 return ENOMEM;
  451         key = mtod(m, struct ieee80211_eapol_key *);
  452         memset(key, 0, sizeof(*key));
  453 
  454         info = EAPOL_KEY_PAIRWISE | EAPOL_KEY_KEYMIC;
  455 
  456         /* copy key replay counter from authenticator */
  457         BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);
  458 
  459         if (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) {
  460                 int keylen;
  461                 /* WPA sets the key length field here */
  462                 keylen = ieee80211_cipher_keylen(ni->ni_rsncipher);
  463                 BE_WRITE_2(key->keylen, keylen);
  464         } else
  465                 info |= EAPOL_KEY_SECURE;
  466 
  467         /* write the key info field */
  468         BE_WRITE_2(key->info, info);
  469 
  470         /* empty key data field */
  471         m->m_pkthdr.len = m->m_len = sizeof(*key);
  472 
  473         if (ic->ic_if.if_flags & IFF_DEBUG)
  474                 printf("%s: sending msg %d/%d of the %s handshake to %s\n",
  475                     ic->ic_if.if_xname, 4, 4, "4-way",
  476                     ether_sprintf(ni->ni_macaddr));
  477 
  478         return ieee80211_send_eapol_key(ic, m, ni, &ni->ni_ptk);
  479 }
  480 
  481 #ifndef IEEE80211_STA_ONLY
  482 /*
  483  * Send Group Key Handshake Message 1 to the supplicant.
  484  */
  485 int
  486 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         ni->ni_rsn_gstate = RSNA_REKEYNEGOTIATING;
  496         if (++ni->ni_rsn_retries > 3) {
  497                 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
  498                     IEEE80211_REASON_GROUP_TIMEOUT);
  499                 ieee80211_node_leave(ic, ni);
  500                 return 0;
  501         }
  502         if (ni->ni_flags & IEEE80211_NODE_REKEY)
  503                 kid = (ic->ic_def_txkey == 1) ? 2 : 1;
  504         else
  505                 kid = ic->ic_def_txkey;
  506         k = &ic->ic_nw_keys[kid];
  507 
  508         m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA,
  509             ((ni->ni_rsnprotos == IEEE80211_PROTO_WPA) ?
  510                 k->k_len : 2 + 6 + k->k_len) +
  511             ((ni->ni_flags & IEEE80211_NODE_MFP) ? 2 + 28 : 0) +
  512             15);
  513         if (m == NULL)
  514                 return ENOMEM;
  515         key = mtod(m, struct ieee80211_eapol_key *);
  516         memset(key, 0, sizeof(*key));
  517 
  518         info = EAPOL_KEY_KEYACK | EAPOL_KEY_KEYMIC | EAPOL_KEY_SECURE |
  519             EAPOL_KEY_ENCRYPTED;
  520 
  521         ni->ni_replaycnt++;
  522         BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);
  523 
  524         frm = (u_int8_t *)&key[1];
  525         if (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) {
  526                 /* WPA does not have GTK KDE */
  527                 BE_WRITE_2(key->keylen, k->k_len);
  528                 memcpy(frm, k->k_key, k->k_len);
  529                 frm += k->k_len;
  530                 info |= (k->k_id & 0x3) << EAPOL_KEY_WPA_KID_SHIFT;
  531                 if (ni->ni_rsncipher == IEEE80211_CIPHER_USEGROUP)
  532                         info |= EAPOL_KEY_WPA_TX;
  533         } else {        /* RSN */
  534                 frm = ieee80211_add_gtk_kde(frm, ni, k);
  535                 if (ni->ni_flags & IEEE80211_NODE_MFP) {
  536                         if (ni->ni_flags & IEEE80211_NODE_REKEY)
  537                                 kid = (ic->ic_igtk_kid == 4) ? 5 : 4;
  538                         else
  539                                 kid = ic->ic_igtk_kid;
  540                         frm = ieee80211_add_igtk_kde(frm,
  541                             &ic->ic_nw_keys[kid]);
  542                 }
  543         }
  544         /* RSC = last transmit sequence number for the GTK */
  545         LE_WRITE_6(key->rsc, k->k_tsc);
  546 
  547         /* write the key info field */
  548         BE_WRITE_2(key->info, info);
  549 
  550         m->m_pkthdr.len = m->m_len = frm - (u_int8_t *)key;
  551 
  552         if (ic->ic_if.if_flags & IFF_DEBUG)
  553                 printf("%s: sending msg %d/%d of the %s handshake to %s\n",
  554                     ic->ic_if.if_xname, 1, 2, "group key",
  555                     ether_sprintf(ni->ni_macaddr));
  556 
  557         return ieee80211_send_eapol_key(ic, m, ni, &ni->ni_ptk);
  558 }
  559 #endif  /* IEEE80211_STA_ONLY */
  560 
  561 /*
  562  * Send Group Key Handshake Message 2 to the authenticator.
  563  */
  564 int
  565 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         m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA, 0);
  573         if (m == NULL)
  574                 return ENOMEM;
  575         key = mtod(m, struct ieee80211_eapol_key *);
  576         memset(key, 0, sizeof(*key));
  577 
  578         info = EAPOL_KEY_KEYMIC | EAPOL_KEY_SECURE;
  579 
  580         /* copy key replay counter from authenticator */
  581         BE_WRITE_8(key->replaycnt, ni->ni_replaycnt);
  582 
  583         if (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) {
  584                 /* WPA sets the key length and key id fields here */
  585                 BE_WRITE_2(key->keylen, k->k_len);
  586                 info |= (k->k_id & 3) << EAPOL_KEY_WPA_KID_SHIFT;
  587         }
  588 
  589         /* write the key info field */
  590         BE_WRITE_2(key->info, info);
  591 
  592         /* empty key data field */
  593         m->m_pkthdr.len = m->m_len = sizeof(*key);
  594 
  595         if (ic->ic_if.if_flags & IFF_DEBUG)
  596                 printf("%s: sending msg %d/%d of the %s handshake to %s\n",
  597                     ic->ic_if.if_xname, 2, 2, "group key",
  598                     ether_sprintf(ni->ni_macaddr));
  599 
  600         return ieee80211_send_eapol_key(ic, m, ni, &ni->ni_ptk);
  601 }
  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 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         m = ieee80211_get_eapol_key(M_DONTWAIT, MT_DATA, 0);
  616         if (m == NULL)
  617                 return ENOMEM;
  618         key = mtod(m, struct ieee80211_eapol_key *);
  619         memset(key, 0, sizeof(*key));
  620 
  621         info |= EAPOL_KEY_REQUEST;
  622         BE_WRITE_2(key->info, info);
  623 
  624         /* in case of TKIP MIC failure, fill the RSC field */
  625         if (info & EAPOL_KEY_ERROR)
  626                 LE_WRITE_6(key->rsc, tsc);
  627 
  628         /* use our separate key replay counter for key requests */
  629         BE_WRITE_8(key->replaycnt, ni->ni_reqreplaycnt);
  630         ni->ni_reqreplaycnt++;
  631 
  632         /* empty key data field */
  633         m->m_pkthdr.len = m->m_len = sizeof(*key);
  634 
  635         if (ic->ic_if.if_flags & IFF_DEBUG)
  636                 printf("%s: sending EAPOL-Key request to %s\n",
  637                     ic->ic_if.if_xname, ether_sprintf(ni->ni_macaddr));
  638 
  639         return ieee80211_send_eapol_key(ic, m, ni, &ni->ni_ptk);
  640 }

Cache object: 453832656887361cd79bb5725a9de30a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.