Le Fri, 15 May 2020 11:02:46 +0200,
Stefan Sperling <[email protected]> a écrit :

> On Fri, May 08, 2020 at 10:53:30AM +0200, Stefan Sperling wrote:
> > So the diff below contains just the reordering fix for drivers using
> > hardware acceleration for WPA.  
> 
> Is there anybody who wants to OK this?
> 
> To recap:
> 
> Currently, CCMP replay checking is skipped for aggregated 11n frames
> on drivers which use CCMP hardware acceleration: athn(4) and iwn(4).
> 
> This diff makes reply checking in that case possible without false
> positives, by updating the last-seen packet number after the
> aggregated subframes, which may be received out of order, have been
> put back into their intended order by ieee80211_input_ba(). The old
> code only works in the single-frame case for 11a/b/g modes where no
> such legitimate re-transmissions can occur.
> 
> > diff refs/heads/master refs/heads/pn
> > blob - 9193ae3c7b5101a86b85b1b3ba48489d75f5150c
> > blob + 8bc189dc146562f7ab0af2f1690fa02676aecfcd
> > --- sys/dev/ic/ar5008.c
> > +++ sys/dev/ic/ar5008.c
> > @@ -794,9 +794,8 @@ ar5008_ccmp_decap(struct athn_softc *sc, struct
> > mbuf * struct ieee80211_frame *wh;
> >     struct ieee80211_rx_ba *ba;
> >     uint64_t pn, *prsc;
> > -   u_int8_t *ivp, *mmie;
> > +   u_int8_t *ivp;
> >     uint8_t tid;
> > -   uint16_t kid;
> >     int hdrlen, hasqos;
> >     uintptr_t entry;
> >  
> > @@ -805,35 +804,8 @@ ar5008_ccmp_decap(struct athn_softc *sc,
> > struct mbuf * ivp = mtod(m, u_int8_t *) + hdrlen;
> >  
> >     /* find key for decryption */
> > -   if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
> > -           k = &ni->ni_pairwise_key;
> > -   } else if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) !=
> > -       IEEE80211_FC0_TYPE_MGT) {
> > -           /* retrieve group data key id from IV field */
> > -           /* check that IV field is present */
> > -           if (m->m_len < hdrlen + 4)
> > -                   return 1;
> > -           kid = ivp[3] >> 6;
> > -           k = &ic->ic_nw_keys[kid];
> > -   } else {
> > -           /* retrieve integrity group key id from MMIE */
> > -           if (m->m_len < sizeof(*wh) + IEEE80211_MMIE_LEN) {
> > -                   return 1;
> > -           }
> > -           /* it is assumed management frames are contiguous
> > */
> > -           mmie = (u_int8_t *)wh + m->m_len -
> > IEEE80211_MMIE_LEN;
> > -           /* check that MMIE is valid */
> > -           if (mmie[0] != IEEE80211_ELEMID_MMIE || mmie[1] !=
> > 16) {
> > -                   return 1;
> > -           }
> > -           kid = LE_READ_2(&mmie[2]);
> > -           if (kid != 4 && kid != 5) {
> > -                   return 1;
> > -           }
> > -           k = &ic->ic_nw_keys[kid];
> > -   }
> > -
> > -   if (k->k_cipher != IEEE80211_CIPHER_CCMP)
> > +   k = ieee80211_get_rxkey(ic, m, ni);
> > +   if (k == NULL || k->k_cipher != IEEE80211_CIPHER_CCMP)
> >             return 1;
> >  
> >     /* Sanity checks to ensure this is really a key we
> > installed. */ @@ -853,7 +825,7 @@ ar5008_ccmp_decap(struct
> > athn_softc *sc, struct mbuf * hasqos = ieee80211_has_qos(wh);
> >     tid = hasqos ? ieee80211_get_qos(wh) & IEEE80211_QOS_TID :
> > 0; ba = hasqos ? &ni->ni_rx_ba[tid] : NULL;
> > -   prsc = &k->k_rsc[0];
> > +   prsc = &k->k_rsc[tid];
> >  
> >     /* Extract the 48-bit PN from the CCMP header. */
> >     pn = (uint64_t)ivp[0]       |
> > @@ -863,30 +835,12 @@ ar5008_ccmp_decap(struct athn_softc *sc,
> > struct mbuf * (uint64_t)ivp[6] << 32 |
> >          (uint64_t)ivp[7] << 40;
> >     if (pn <= *prsc) {
> > -           if (hasqos && ba->ba_state == IEEE80211_BA_AGREED)
> > {
> > -                   /*
> > -                    * This is an A-MPDU subframe.
> > -                    * Such frames may be received out of
> > order due to
> > -                    * legitimate retransmissions of failed
> > subframes
> > -                    * in previous A-MPDUs. Duplicates will be
> > handled
> > -                    * in ieee80211_inputm() as part of A-MPDU
> > reordering.
> > -                    *
> > -                    * XXX TODO We can probably do better than
> > this! Store
> > -                    * re-ordered PN in BA agreement state and
> > check it?
> > -                    */
> > -           } else {
> > -                   ic->ic_stats.is_ccmp_replays++;
> > -                   return 1;
> > -           }
> > +           ic->ic_stats.is_ccmp_replays++;
> > +           return 1;
> >     }
> > -   /* Update last seen packet number. */
> > -   *prsc = pn;
> > +   /* Last seen packet number is updated in
> > ieee80211_inputm(). */ 
> > -   /* Clear Protected bit and strip IV. */
> > -   wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
> > -   memmove(mtod(m, caddr_t) + IEEE80211_CCMP_HDRLEN, wh,
> > hdrlen);
> > -   m_adj(m, IEEE80211_CCMP_HDRLEN);
> > -   /* Strip MIC. */
> > +   /* Strip MIC. IV will be stripped by ieee80211_inputm(). */
> >     m_adj(m, -IEEE80211_CCMP_MICLEN);
> >     return 0;
> >  }
> > blob - 6b6331d167a881a526b9d0a30f7f452882fee19a
> > blob + 620cbd4c138516398a4683d83c1b6bf8aac57c82
> > --- sys/dev/pci/if_iwn.c
> > +++ sys/dev/pci/if_iwn.c
> > @@ -1936,47 +1936,13 @@ iwn_ccmp_decap(struct iwn_softc *sc, struct
> > mbuf *m, s (uint64_t)ivp[6] << 32 |
> >          (uint64_t)ivp[7] << 40;
> >     if (pn <= *prsc) {
> > -           if (hasqos && ba->ba_state == IEEE80211_BA_AGREED)
> > {
> > -                   /*
> > -                    * This is an A-MPDU subframe.
> > -                    * Such frames may be received out of
> > order due to
> > -                    * legitimate retransmissions of failed
> > subframes
> > -                    * in previous A-MPDUs. Duplicates will be
> > handled
> > -                    * in ieee80211_inputm() as part of A-MPDU
> > reordering.
> > -                    */
> > -           } else if (ieee80211_has_seq(wh)) {
> > -                   /*
> > -                    * Not necessarily a replayed frame since
> > we did not
> > -                    * check the sequence number of the 802.11
> > header yet.
> > -                    */
> > -                   int nrxseq, orxseq;
> > -
> > -                   nrxseq = letoh16(*(u_int16_t *)wh->i_seq)
> > >>
> > -                       IEEE80211_SEQ_SEQ_SHIFT;
> > -                   if (hasqos)
> > -                           orxseq = ni->ni_qos_rxseqs[tid];
> > -                   else
> > -                           orxseq = ni->ni_rxseq;
> > -                   if (nrxseq < orxseq) {
> > -                           DPRINTF(("CCMP replayed (n=%d <
> > o=%d)\n",
> > -                               nrxseq, orxseq));
> > -                           ic->ic_stats.is_ccmp_replays++;
> > -                           return 1;
> > -                   }
> > -           } else {
> > -                   DPRINTF(("CCMP replayed\n"));
> > -                   ic->ic_stats.is_ccmp_replays++;
> > -                   return 1;
> > -           }
> > +           DPRINTF(("CCMP replayed\n"));
> > +           ic->ic_stats.is_ccmp_replays++;
> > +           return 1;
> >     }
> > -   /* Update last seen packet number. */
> > -   *prsc = pn;
> > +   /* Last seen packet number is updated in
> > ieee80211_inputm(). */ 
> > -   /* Clear Protected bit and strip IV. */
> > -   wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
> > -   memmove(mtod(m, caddr_t) + IEEE80211_CCMP_HDRLEN, wh,
> > hdrlen);
> > -   m_adj(m, IEEE80211_CCMP_HDRLEN);
> > -   /* Strip MIC. */
> > +   /* Strip MIC. IV will be stripped by ieee80211_inputm(). */
> >     m_adj(m, -IEEE80211_CCMP_MICLEN);
> >     return 0;
> >  }
> > blob - 23514161af1c3576b1f594a1068f95a359b4ea1b
> > blob + 87bbeeabbb06f66d1ecde98b147c18df98143ae9
> > --- sys/dev/pci/if_wpi.c
> > +++ sys/dev/pci/if_wpi.c
> > @@ -1132,6 +1132,7 @@ wpi_calib_timeout(void *arg)
> >  int
> >  wpi_ccmp_decap(struct wpi_softc *sc, struct mbuf *m, struct
> > ieee80211_key *k) {
> > +   struct ieee80211com *ic = &sc->sc_ic;
> >     struct ieee80211_frame *wh;
> >     uint64_t pn, *prsc;
> >     uint8_t *ivp;
> > @@ -1159,21 +1160,13 @@ wpi_ccmp_decap(struct wpi_softc *sc, struct
> > mbuf *m, s (uint64_t)ivp[6] << 32 |
> >          (uint64_t)ivp[7] << 40;
> >     if (pn <= *prsc) {
> > -           /*
> > -            * Not necessarily a replayed frame since we did
> > not check
> > -            * the sequence number of the 802.11 header yet.
> > -            */
> >             DPRINTF(("CCMP replayed\n"));
> > +           ic->ic_stats.is_ccmp_replays++;
> >             return 1;
> >     }
> > -   /* Update last seen packet number. */
> > -   *prsc = pn;
> > +   /* Last seen packet number is updated in
> > ieee80211_inputm(). */ 
> > -   /* Clear Protected bit and strip IV. */
> > -   wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
> > -   memmove(mtod(m, caddr_t) + IEEE80211_CCMP_HDRLEN, wh,
> > hdrlen);
> > -   m_adj(m, IEEE80211_CCMP_HDRLEN);
> > -   /* Strip MIC. */
> > +   /* Strip MIC. IV will be stripped by ieee80211_inputm(). */
> >     m_adj(m, -IEEE80211_CCMP_MICLEN);
> >     return 0;
> >  }
> > blob - f7683fc8f15fb5bdca674900571d0c9d0ca36079
> > blob + bf287803d05a86f4f6113b44206382a26b188b05
> > --- sys/net80211/ieee80211_crypto.c
> > +++ sys/net80211/ieee80211_crypto.c
> > @@ -209,6 +209,50 @@ ieee80211_get_txkey(struct ieee80211com *ic,
> > const str return &ic->ic_nw_keys[kid];
> >  }
> >  
> > +struct ieee80211_key *
> > +ieee80211_get_rxkey(struct ieee80211com *ic, struct mbuf *m,
> > +    struct ieee80211_node *ni)
> > +{
> > +   struct ieee80211_key *k = NULL;
> > +   struct ieee80211_frame *wh;
> > +   u_int16_t kid;
> > +   u_int8_t *ivp, *mmie;
> > +   int hdrlen;
> > +
> > +   wh = mtod(m, struct ieee80211_frame *);
> > +   if ((ic->ic_flags & IEEE80211_F_RSNON) &&
> > +       !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
> > +       ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP) {
> > +           k = &ni->ni_pairwise_key;
> > +   } else if (!IEEE80211_IS_MULTICAST(wh->i_addr1) ||
> > +       (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) !=
> > +       IEEE80211_FC0_TYPE_MGT) {
> > +           /* retrieve group data key id from IV field */
> > +           hdrlen = ieee80211_get_hdrlen(wh);
> > +           /* check that IV field is present */
> > +           if (m->m_len < hdrlen + 4)
> > +                   return NULL;
> > +           ivp = (u_int8_t *)wh + hdrlen;
> > +           kid = ivp[3] >> 6;
> > +           k = &ic->ic_nw_keys[kid];
> > +   } else {
> > +           /* retrieve integrity group key id from MMIE */
> > +           if (m->m_len < sizeof(*wh) + IEEE80211_MMIE_LEN)
> > +                   return NULL;
> > +           /* it is assumed management frames are contiguous
> > */
> > +           mmie = (u_int8_t *)wh + m->m_len -
> > IEEE80211_MMIE_LEN;
> > +           /* check that MMIE is valid */
> > +           if (mmie[0] != IEEE80211_ELEMID_MMIE || mmie[1] !=
> > 16)
> > +                   return NULL;
> > +           kid = LE_READ_2(&mmie[2]);
> > +           if (kid != 4 && kid != 5)
> > +                   return NULL;
> > +           k = &ic->ic_nw_keys[kid];
> > +   }
> > +
> > +   return k;
> > +}
> > +
> >  struct mbuf *
> >  ieee80211_encrypt(struct ieee80211com *ic, struct mbuf *m0,
> >      struct ieee80211_key *k)
> > @@ -241,54 +285,11 @@ struct mbuf *
> >  ieee80211_decrypt(struct ieee80211com *ic, struct mbuf *m0,
> >      struct ieee80211_node *ni)
> >  {
> > -   struct ieee80211_frame *wh;
> >     struct ieee80211_key *k;
> > -   u_int8_t *ivp, *mmie;
> > -   u_int16_t kid;
> > -   int hdrlen;
> >  
> >     /* find key for decryption */
> > -   wh = mtod(m0, struct ieee80211_frame *);
> > -   if ((ic->ic_flags & IEEE80211_F_RSNON) &&
> > -       !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
> > -       ni->ni_rsncipher != IEEE80211_CIPHER_USEGROUP) {
> > -           k = &ni->ni_pairwise_key;
> > -
> > -   } else if (!IEEE80211_IS_MULTICAST(wh->i_addr1) ||
> > -       (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) !=
> > -       IEEE80211_FC0_TYPE_MGT) {
> > -           /* retrieve group data key id from IV field */
> > -           hdrlen = ieee80211_get_hdrlen(wh);
> > -           /* check that IV field is present */
> > -           if (m0->m_len < hdrlen + 4) {
> > -                   m_freem(m0);
> > -                   return NULL;
> > -           }
> > -           ivp = (u_int8_t *)wh + hdrlen;
> > -           kid = ivp[3] >> 6;
> > -           k = &ic->ic_nw_keys[kid];
> > -   } else {
> > -           /* retrieve integrity group key id from MMIE */
> > -           if (m0->m_len < sizeof(*wh) + IEEE80211_MMIE_LEN) {
> > -                   m_freem(m0);
> > -                   return NULL;
> > -           }
> > -           /* it is assumed management frames are contiguous
> > */
> > -           mmie = (u_int8_t *)wh + m0->m_len -
> > IEEE80211_MMIE_LEN;
> > -           /* check that MMIE is valid */
> > -           if (mmie[0] != IEEE80211_ELEMID_MMIE || mmie[1] !=
> > 16) {
> > -                   m_freem(m0);
> > -                   return NULL;
> > -           }
> > -           kid = LE_READ_2(&mmie[2]);
> > -           if (kid != 4 && kid != 5) {
> > -                   m_freem(m0);
> > -                   return NULL;
> > -           }
> > -           k = &ic->ic_nw_keys[kid];
> > -   }
> > -
> > -   if ((k->k_flags & IEEE80211_KEY_SWCRYPTO) == 0) {
> > +   k = ieee80211_get_rxkey(ic, m0, ni);
> > +   if (k == NULL || (k->k_flags & IEEE80211_KEY_SWCRYPTO) ==
> > 0) { m_free(m0);
> >             return NULL;
> >     }
> > blob - a3bc45c699af9a53dbdad4a39e984c00999b105a
> > blob + f54fff2981e70909d96a4c8ed66d0c1ea664d6ac
> > --- sys/net80211/ieee80211_crypto.h
> > +++ sys/net80211/ieee80211_crypto.h
> > @@ -160,6 +160,8 @@ void    ieee80211_tkip_delete_key(struct
> > ieee80211com *, struct ieee80211_key *);
> >  struct     mbuf *ieee80211_tkip_encrypt(struct ieee80211com *,
> >         struct mbuf *, struct ieee80211_key *);
> > +int        ieee80211_tkip_get_tsc(uint64_t *, uint64_t **, struct
> > mbuf *,
> > +       struct ieee80211_key *);
> >  struct     mbuf *ieee80211_tkip_decrypt(struct ieee80211com *,
> >         struct mbuf *, struct ieee80211_key *);
> >  void       ieee80211_tkip_mic(struct mbuf *, int, const u_int8_t
> > *, @@ -173,6 +175,8 @@ int  ieee80211_ccmp_set_key(struct
> > ieee80211com *, stru void   ieee80211_ccmp_delete_key(struct
> > ieee80211com *, struct ieee80211_key *);
> >  struct     mbuf *ieee80211_ccmp_encrypt(struct ieee80211com *,
> > struct mbuf *,
> > +       struct ieee80211_key *);
> > +int        ieee80211_ccmp_get_pn(uint64_t *, uint64_t **, struct
> > mbuf *, struct ieee80211_key *);
> >  struct     mbuf *ieee80211_ccmp_decrypt(struct ieee80211com *,
> > struct mbuf *, struct ieee80211_key *);
> > blob - f4c8748602f910f75ab4f4eea042df80e398d244
> > blob + 5885e174818b83fc20e24e5fa31b721df6275c4a
> > --- sys/net80211/ieee80211_crypto_ccmp.c
> > +++ sys/net80211/ieee80211_crypto_ccmp.c
> > @@ -300,6 +300,45 @@ ieee80211_ccmp_encrypt(struct ieee80211com
> > *ic, struct return NULL;
> >  }
> >  
> > +int
> > +ieee80211_ccmp_get_pn(uint64_t *pn, uint64_t **prsc, struct mbuf
> > *m,
> > +    struct ieee80211_key *k)
> > +{
> > +   struct ieee80211_frame *wh;
> > +   int hdrlen;
> > +   const u_int8_t *ivp;
> > +
> > +   wh = mtod(m, struct ieee80211_frame *);
> > +   hdrlen = ieee80211_get_hdrlen(wh);
> > +   if (m->m_pkthdr.len < hdrlen + IEEE80211_CCMP_HDRLEN)
> > +           return EINVAL;
> > +
> > +   ivp = (u_int8_t *)wh + hdrlen;
> > +
> > +   /* check that ExtIV bit is set */
> > +   if (!(ivp[3] & IEEE80211_WEP_EXTIV))
> > +           return EINVAL;
> > +
> > +   /* retrieve last seen packet number for this frame
> > type/priority */
> > +   if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
> > +       IEEE80211_FC0_TYPE_DATA) {
> > +           u_int8_t tid = ieee80211_has_qos(wh) ?
> > +               ieee80211_get_qos(wh) & IEEE80211_QOS_TID : 0;
> > +           *prsc = &k->k_rsc[tid];
> > +   } else  /* 11w: management frames have their own
> > counters */
> > +           *prsc = &k->k_mgmt_rsc;
> > +
> > +   /* extract the 48-bit PN from the CCMP header */
> > +   *pn = (u_int64_t)ivp[0]      |
> > +        (u_int64_t)ivp[1] <<  8 |
> > +        (u_int64_t)ivp[4] << 16 |
> > +        (u_int64_t)ivp[5] << 24 |
> > +        (u_int64_t)ivp[6] << 32 |
> > +        (u_int64_t)ivp[7] << 40;
> > +
> > +   return 0;
> > +}
> > +
> >  struct mbuf *
> >  ieee80211_ccmp_decrypt(struct ieee80211com *ic, struct mbuf *m0,
> >      struct ieee80211_key *k)
> > @@ -307,7 +346,7 @@ ieee80211_ccmp_decrypt(struct ieee80211com *ic,
> > struct struct ieee80211_ccmp_ctx *ctx = k->k_priv;
> >     struct ieee80211_frame *wh;
> >     u_int64_t pn, *prsc;
> > -   const u_int8_t *ivp, *src;
> > +   const u_int8_t *src;
> >     u_int8_t *dst;
> >     u_int8_t mic0[IEEE80211_CCMP_MICLEN];
> >     u_int8_t a[16], b[16], s0[16], s[16];
> > @@ -318,35 +357,20 @@ ieee80211_ccmp_decrypt(struct ieee80211com
> > *ic, struct 
> >     wh = mtod(m0, struct ieee80211_frame *);
> >     hdrlen = ieee80211_get_hdrlen(wh);
> > -   ivp = (u_int8_t *)wh + hdrlen;
> > -
> >     if (m0->m_pkthdr.len < hdrlen + IEEE80211_CCMP_HDRLEN +
> >         IEEE80211_CCMP_MICLEN) {
> >             m_freem(m0);
> >             return NULL;
> >     }
> > -   /* check that ExtIV bit is set */
> > -   if (!(ivp[3] & IEEE80211_WEP_EXTIV)) {
> > +
> > +   /*
> > +    * Get the frame's Packet Number (PN) and a pointer to our
> > last-seen
> > +    * Receive Sequence Counter (RSC) which we can use to
> > detect replays.
> > +    */
> > +   if (ieee80211_ccmp_get_pn(&pn, &prsc, m0, k) != 0) {
> >             m_freem(m0);
> >             return NULL;
> >     }
> > -
> > -   /* retrieve last seen packet number for this frame
> > type/priority */
> > -   if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
> > -       IEEE80211_FC0_TYPE_DATA) {
> > -           u_int8_t tid = ieee80211_has_qos(wh) ?
> > -               ieee80211_get_qos(wh) & IEEE80211_QOS_TID : 0;
> > -           prsc = &k->k_rsc[tid];
> > -   } else  /* 11w: management frames have their own
> > counters */
> > -           prsc = &k->k_mgmt_rsc;
> > -
> > -   /* extract the 48-bit PN from the CCMP header */
> > -   pn = (u_int64_t)ivp[0]       |
> > -        (u_int64_t)ivp[1] <<  8 |
> > -        (u_int64_t)ivp[4] << 16 |
> > -        (u_int64_t)ivp[5] << 24 |
> > -        (u_int64_t)ivp[6] << 32 |
> > -        (u_int64_t)ivp[7] << 40;
> >     if (pn <= *prsc) {
> >             /* replayed frame, discard */
> >             ic->ic_stats.is_ccmp_replays++;
> > blob - 70fbe7c9769f9dbd5e9f3cc2fb1961d1282c9e2b
> > blob + 3473de8eb99d01dce20a0862275a3339e5031a10
> > --- sys/net80211/ieee80211_crypto_tkip.c
> > +++ sys/net80211/ieee80211_crypto_tkip.c
> > @@ -313,6 +313,42 @@ ieee80211_tkip_encrypt(struct ieee80211com
> > *ic, struct return NULL;
> >  }
> >  
> > +int
> > +ieee80211_tkip_get_tsc(uint64_t *tsc, uint64_t **prsc, struct mbuf
> > *m,
> > +    struct ieee80211_key *k)
> > +{
> > +   struct ieee80211_frame *wh;
> > +   int hdrlen;
> > +   u_int8_t tid;
> > +   const u_int8_t *ivp;
> > +
> > +   wh = mtod(m, struct ieee80211_frame *);
> > +   hdrlen = ieee80211_get_hdrlen(wh);
> > +
> > +   if (m->m_pkthdr.len < hdrlen + IEEE80211_TKIP_HDRLEN)
> > +           return EINVAL;
> > +
> > +   ivp = (u_int8_t *)wh + hdrlen;
> > +   /* check that ExtIV bit is set */
> > +   if (!(ivp[3] & IEEE80211_WEP_EXTIV))
> > +           return EINVAL;
> > +
> > +   /* Retrieve last seen packet number for this frame
> > priority. */
> > +   tid = ieee80211_has_qos(wh) ?
> > +       ieee80211_get_qos(wh) & IEEE80211_QOS_TID : 0;
> > +   *prsc = &k->k_rsc[tid];
> > +
> > +   /* extract the 48-bit TSC from the TKIP header */
> > +   *tsc = (u_int64_t)ivp[2]      |
> > +         (u_int64_t)ivp[0] <<  8 |
> > +         (u_int64_t)ivp[4] << 16 |
> > +         (u_int64_t)ivp[5] << 24 |
> > +         (u_int64_t)ivp[6] << 32 |
> > +         (u_int64_t)ivp[7] << 40;
> > +
> > +   return 0;
> > +}
> > +
> >  struct mbuf *
> >  ieee80211_tkip_decrypt(struct ieee80211com *ic, struct mbuf *m0,
> >      struct ieee80211_key *k)
> > @@ -324,8 +360,7 @@ ieee80211_tkip_decrypt(struct ieee80211com *ic,
> > struct u_int8_t mic[IEEE80211_TKIP_MICLEN];
> >     u_int64_t tsc, *prsc;
> >     u_int32_t crc, crc0;
> > -   u_int8_t *ivp, *mic0;
> > -   u_int8_t tid;
> > +   u_int8_t *mic0;
> >     struct mbuf *n0, *m, *n;
> >     int hdrlen, left, moff, noff, len;
> >  
> > @@ -337,25 +372,15 @@ ieee80211_tkip_decrypt(struct ieee80211com
> > *ic, struct return NULL;
> >     }
> >  
> > -   ivp = (u_int8_t *)wh + hdrlen;
> > -   /* check that ExtIV bit is set */
> > -   if (!(ivp[3] & IEEE80211_WEP_EXTIV)) {
> > +   /*
> > +    * Get the frame's Tansmit Sequence Counter (TSC), and a
> > pointer to
> > +    * our last-seen Receive Sequence Counter (RSC) with which
> > we can
> > +    * detect replays.
> > +    */
> > +   if (ieee80211_tkip_get_tsc(&tsc, &prsc, m0, k) != 0) {
> >             m_freem(m0);
> >             return NULL;
> >     }
> > -
> > -   /* retrieve last seen packet number for this frame
> > priority */
> > -   tid = ieee80211_has_qos(wh) ?
> > -       ieee80211_get_qos(wh) & IEEE80211_QOS_TID : 0;
> > -   prsc = &k->k_rsc[tid];
> > -
> > -   /* extract the 48-bit TSC from the TKIP header */
> > -   tsc = (u_int64_t)ivp[2]       |
> > -         (u_int64_t)ivp[0] <<  8 |
> > -         (u_int64_t)ivp[4] << 16 |
> > -         (u_int64_t)ivp[5] << 24 |
> > -         (u_int64_t)ivp[6] << 32 |
> > -         (u_int64_t)ivp[7] << 40;
> >     if (tsc <= *prsc) {
> >             /* replayed frame, discard */
> >             ic->ic_stats.is_tkip_replays++;
> > blob - d802a15ad6ca1eaca39e681fd5e59297fc2ef464
> > blob + 2e4714aeaa9a7853b2ba65bacb7d45e6e338d8f8
> > --- sys/net80211/ieee80211_input.c
> > +++ sys/net80211/ieee80211_input.c
> > @@ -58,6 +58,8 @@
> >  #include <net80211/ieee80211_var.h>
> >  #include <net80211/ieee80211_priv.h>
> >  
> > +struct     mbuf *ieee80211_input_hwdecrypt(struct ieee80211com
> > *,
> > +       struct ieee80211_node *, struct mbuf *);
> >  struct     mbuf *ieee80211_defrag(struct ieee80211com *, struct
> > mbuf *, int); void  ieee80211_defrag_timeout(void *);
> >  void       ieee80211_input_ba(struct ieee80211com *, struct mbuf
> > *, @@ -147,6 +149,86 @@ ieee80211_get_hdrlen(const struct
> > ieee80211_frame *wh) return size;
> >  }
> >  
> > +/* Post-processing for drivers which perform decryption in
> > hardware. */ +struct mbuf *
> > +ieee80211_input_hwdecrypt(struct ieee80211com *ic, struct
> > ieee80211_node *ni,
> > +    struct mbuf *m)
> > +{
> > +   struct ieee80211_key *k;
> > +   struct ieee80211_frame *wh;
> > +   uint64_t pn, *prsc;
> > +   int hdrlen;
> > +
> > +   k = ieee80211_get_rxkey(ic, m, ni);
> > +   if (k == NULL)
> > +           return NULL;
> > +   
> > +   wh = mtod(m, struct ieee80211_frame *);
> > +   hdrlen = ieee80211_get_hdrlen(wh);
> > +
> > +   /*
> > +    * Update the last-seen packet number (PN) for drivers
> > using hardware
> > +    * crypto offloading. This cannot be done by drivers
> > because A-MPDU
> > +    * reordering needs to occur before a valid lower bound
> > can be
> > +    * determined for the PN. Drivers will read the PN we
> > write here and
> > +    * are expected to discard replayed frames based on it.
> > +    * Drivers are expected to leave the IV of decrypted
> > frames intact
> > +    * so we can update the last-seen PN and strip the IV here.
> > +    */
> > +   switch (k->k_cipher) {
> > +   case IEEE80211_CIPHER_CCMP:
> > +           if (!(wh->i_fc[1] & IEEE80211_FC1_PROTECTED)) {
> > +                   /* drop unencrypted */
> > +                   ic->ic_stats.is_rx_unencrypted++;
> > +                   return NULL;
> > +           }
> > +           if (ieee80211_ccmp_get_pn(&pn, &prsc, m, k) != 0)
> > +                   return NULL;
> > +           if (pn <= *prsc) {
> > +                   ic->ic_stats.is_ccmp_replays++;
> > +                   return NULL;
> > +           }
> > +
> > +           /* Update last-seen packet number. */
> > +           *prsc = pn;
> > +
> > +           /* Clear Protected bit and strip IV. */
> > +           wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
> > +           memmove(mtod(m, caddr_t) + IEEE80211_CCMP_HDRLEN,
> > wh, hdrlen);
> > +           m_adj(m, IEEE80211_CCMP_HDRLEN);
> > +           /* Drivers are expected to strip the MIC. */
> > +           break;
> > +    case IEEE80211_CIPHER_TKIP:
> > +           if (!(wh->i_fc[1] & IEEE80211_FC1_PROTECTED)) {
> > +                   /* drop unencrypted */
> > +                   ic->ic_stats.is_rx_unencrypted++;
> > +                   return NULL;
> > +           }
> > +           if (ieee80211_tkip_get_tsc(&pn, &prsc, m, k) != 0)
> > +                   return NULL;
> > +
> > +           if (pn <= *prsc) {
> > +                   ic->ic_stats.is_tkip_replays++;
> > +                   return NULL;
> > +           }
> > +
> > +           /* Update last-seen packet number. */
> > +           *prsc = pn;
> > +
> > +           /* Clear Protected bit and strip IV. */
> > +           wh = mtod(m, struct ieee80211_frame *);
> > +           wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
> > +           memmove(mtod(m, caddr_t) + IEEE80211_TKIP_HDRLEN,
> > wh, hdrlen);
> > +           m_adj(m, IEEE80211_TKIP_HDRLEN);
> > +           /* Drivers are expected to strip the MIC. */
> > +           break;
> > +   default:
> > +           break;
> > +   }
> > +
> > +   return m;
> > +}
> > +
> >  /*
> >   * Process a received frame.  The node associated with the sender
> >   * should be supplied.  If nothing was found in the node table then
> > @@ -454,8 +536,12 @@ ieee80211_inputm(struct ifnet *ifp, struct
> > mbuf *m, st ic->ic_stats.is_rx_wepfail++;
> >                                     goto err;
> >                             }
> > -                           wh = mtod(m, struct
> > ieee80211_frame *);
> > +                   } else {
> > +                           m = ieee80211_input_hwdecrypt(ic,
> > ni, m);
> > +                           if (m == NULL)
> > +                                   goto err;
> >                     }
> > +                   wh = mtod(m, struct ieee80211_frame *);
> >             } else if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
> > || (rxi->rxi_flags & IEEE80211_RXI_HWDEC)) {
> >                     /* frame encrypted but protection off for
> > Rx */
> > 
> >   
> 

No regression found with following devices, ok solene@

iwn0 at pci2 dev 0 function 0 "Intel WiFi Link 5100" rev 0x00: msi, MIMO 1T2R, 
MoW, address 00:1e:65:41:f4:14
urtwn0 at uhub0 port 1 configuration 1 interface 0 "Realtek 802.11n NIC" rev 
2.00/0.00 addr 2
athn0 at uhub0 port 1 configuration 1 interface 0 "ATHEROS USB2.0 WLAN" rev 
2.00/1.08 addr 2

Reply via email to