]> err.no Git - linux-2.6/commitdiff
[MAC80211]: rework hardware crypto flags
authorJohannes Berg <johannes@sipsolutions.net>
Fri, 14 Sep 2007 15:10:25 +0000 (11:10 -0400)
committerDavid S. Miller <davem@sunset.davemloft.net>
Wed, 10 Oct 2007 23:49:27 +0000 (16:49 -0700)
This patch reworks the various hardware crypto related
flags to make them more local, i.e. put them with each
key or each packet instead of into the hw struct.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Acked-by: Michael Wu <flamingice@sourmilk.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/wireless/rtl8187_dev.c
include/net/mac80211.h
net/mac80211/rx.c
net/mac80211/tx.c
net/mac80211/wpa.c

index 9db9ece31b494022a0a59e3be15c741b48d701f1..7dbf11e30db31980dbc9ffd623bddad2e6de2b0a 100644 (file)
@@ -605,8 +605,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
        priv->modes[1].channels = priv->channels;
        priv->mode = IEEE80211_IF_TYPE_MGMT;
        dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-                    IEEE80211_HW_RX_INCLUDES_FCS |
-                    IEEE80211_HW_WEP_INCLUDE_IV;
+                    IEEE80211_HW_RX_INCLUDES_FCS;
        dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr);
        dev->queues = 1;
        dev->max_rssi = 65;
index fcb7e3f9c6691f2dce3bdaf3af77c26452767e70..9137579c12a47e5fc64231497dafb344b8d26900 100644 (file)
@@ -240,6 +240,8 @@ struct ieee80211_rx_status {
 #define RX_FLAG_MMIC_ERROR     (1<<0)
 #define RX_FLAG_DECRYPTED      (1<<1)
 #define RX_FLAG_RADIOTAP       (1<<2)
+#define RX_FLAG_MMIC_STRIPPED  (1<<3)
+#define RX_FLAG_IV_STRIPPED    (1<<4)
        int flag;
 };
 
@@ -402,6 +404,16 @@ typedef enum {
  * that situation it should reject that key.
  */
 #define IEEE80211_KEY_FLAG_WMM_STA     (1<<0)
+/*
+ * This flag should be set by the driver if it requires
+ * IV generation in software for this key.
+ */
+#define IEEE80211_KEY_FLAG_GENERATE_IV (1<<1)
+/*
+ * This flag should be set by the driver if it requires
+ * MMIC generation in software for this key.
+ */
+#define IEEE80211_KEY_FLAG_GENERATE_MMIC (1<<2)
 
 struct ieee80211_key_conf {
        /*
@@ -465,17 +477,7 @@ struct ieee80211_hw {
         */
 #define IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE (1<<1)
 
-       /*
-        * Some devices handle decryption internally and do not
-        * indicate whether the frame was encrypted (unencrypted frames
-        * will be dropped by the hardware, unless specifically allowed
-        * through.)
-        * It is permissible to not handle all encrypted frames and fall
-        * back to software encryption; however, if this flag is set
-        * unencrypted frames must be dropped unless the driver is told
-        * otherwise via the set_ieee8021x() callback.
-        */
-#define IEEE80211_HW_DEVICE_HIDES_WEP (1<<2)
+/* hole at 2 */
 
        /* Whether RX frames passed to ieee80211_rx() include FCS in the end */
 #define IEEE80211_HW_RX_INCLUDES_FCS (1<<3)
@@ -488,32 +490,13 @@ struct ieee80211_hw {
         * can fetch them with ieee80211_get_buffered_bc(). */
 #define IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING (1<<4)
 
-       /*
-        * This flag is only relevant if hardware encryption is used.
-        * If set, it has two meanings:
-        *  1) the IV and ICV are present in received frames that have
-        *     been decrypted (unless IEEE80211_HW_DEVICE_HIDES_WEP is
-        *     also set)
-        *  2) on transmission, the IV should be generated in software.
-        *
-        * Please let us know if you *don't* use this flag, the stack would
-        * really like to be able to get the IV to keep key statistics
-        * accurate.
-        */
-#define IEEE80211_HW_WEP_INCLUDE_IV (1<<5)
+/* hole at 5 */
 
 /* hole at 6 */
 
 /* hole at 7 */
 
-       /*
-        * Some devices handle Michael MIC internally and do not include MIC in
-        * the received packets passed up. This flag must be set for such
-        * devices. The 'encryption' frame control bit is expected to be still
-        * set in the IEEE 802.11 header with this option unlike with the
-        * IEEE80211_HW_DEVICE_HIDES_WEP flag.
-        */
-#define IEEE80211_HW_DEVICE_STRIPS_MIC (1<<8)
+/* hole at 8 */
 
        /* Device is capable of performing full monitor mode even during
         * normal operation. */
@@ -527,8 +510,6 @@ struct ieee80211_hw {
         * specified in the device's EEPROM */
 #define IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED (1<<11)
 
-       /* calculate Michael MIC for an MSDU when doing hwcrypto */
-#define IEEE80211_HW_TKIP_INCLUDE_MMIC (1<<12)
        /* Do TKIP phase1 key mixing in stack to support cards only do
         * phase2 key mixing when doing hwcrypto */
 #define IEEE80211_HW_TKIP_REQ_PHASE1_KEY (1<<13)
index 8c6e290892162c4568f6026d49dda1b0f999496a..28b8b6af4c42cca3c92082551d28ed588b3f8664 100644 (file)
@@ -363,7 +363,8 @@ ieee80211_rx_h_load_key(struct ieee80211_txrx_data *rx)
                 * we somehow allow the driver to tell us which key
                 * the hardware used if this flag is set?
                 */
-               if (!(rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV))
+               if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
+                   (rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED))
                        return TXRX_CONTINUE;
 
                hdrlen = ieee80211_get_hdrlen(rx->fc);
@@ -534,8 +535,8 @@ ieee80211_rx_h_wep_weak_iv_detection(struct ieee80211_txrx_data *rx)
                return TXRX_CONTINUE;
 
        /* Check for weak IVs, if hwaccel did not remove IV from the frame */
-       if ((rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) ||
-           !(rx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
+       if (!(rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED) ||
+           !(rx->u.rx.status->flag & RX_FLAG_DECRYPTED))
                if (ieee80211_wep_is_weak_iv(rx->skb, rx->key))
                        rx->sta->wep_weak_iv_count++;
 
@@ -559,15 +560,14 @@ ieee80211_rx_h_wep_decrypt(struct ieee80211_txrx_data *rx)
                return TXRX_DROP;
        }
 
-       if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED) ||
-           !(rx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
+       if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED)) {
                if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) {
                        if (net_ratelimit())
                                printk(KERN_DEBUG "%s: RX WEP frame, decrypt "
                                       "failed\n", rx->dev->name);
                        return TXRX_DROP;
                }
-       } else if (rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) {
+       } else if (!(rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED)) {
                ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key);
                /* remove ICV */
                skb_trim(rx->skb, rx->skb->len - 4);
@@ -898,13 +898,10 @@ static ieee80211_txrx_result
 ieee80211_rx_h_drop_unencrypted(struct ieee80211_txrx_data *rx)
 {
        /*
-        * Pass through unencrypted frames if the hardware might have
-        * decrypted them already without telling us, but that can only
-        * be true if we either didn't find a key or the found key is
-        * uploaded to the hardware.
+        * Pass through unencrypted frames if the hardware has
+        * decrypted them already.
         */
-       if ((rx->local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP) &&
-           (!rx->key || (rx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)))
+       if (rx->u.rx.status->flag & RX_FLAG_DECRYPTED)
                return TXRX_CONTINUE;
 
        /* Drop unencrypted frames if key is set. */
@@ -1212,8 +1209,7 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev,
                goto ignore;
        }
 
-       if ((rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) &&
-           rx->sdata->type == IEEE80211_IF_TYPE_AP && keyidx) {
+       if (rx->sdata->type == IEEE80211_IF_TYPE_AP && keyidx) {
                /* AP with Pairwise keys support should never receive Michael
                 * MIC errors for non-zero keyidx because these are reserved
                 * for group keys and only the AP is sending real multicast
index 08d221674bc04ebe6410a97a70e9c1d900e98d7b..e2ae1e1fcc7b6fed6b7afba427933cc5877f040d 100644 (file)
@@ -545,9 +545,8 @@ static int wep_encrypt_skb(struct ieee80211_txrx_data *tx, struct sk_buff *skb)
                        return -1;
        } else {
                tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx;
-               if (tx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) {
-                       if (ieee80211_wep_add_iv(tx->local, skb, tx->key) ==
-                           NULL)
+               if (tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) {
+                       if (!ieee80211_wep_add_iv(tx->local, skb, tx->key))
                                return -1;
                }
        }
index 775f89e42a43e7325082a0b0e4b392e2fdc6c741..a23531cef5b0da79f972f8f9ab2c9010563a2802 100644 (file)
@@ -91,7 +91,7 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx)
 
        if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
            !(tx->flags & IEEE80211_TXRXD_FRAGMENTED) &&
-           !(tx->local->hw.flags & IEEE80211_HW_TKIP_INCLUDE_MMIC) &&
+           !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) &&
            !wpa_test) {
                /* hwaccel - with no need for preallocated room for Michael MIC
                 */
@@ -138,26 +138,13 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx)
        /*
         * No way to verify the MIC if the hardware stripped it
         */
-       if (rx->local->hw.flags & IEEE80211_HW_DEVICE_STRIPS_MIC)
+       if (rx->u.rx.status->flag & RX_FLAG_MMIC_STRIPPED)
                return TXRX_CONTINUE;
 
        if (!rx->key || rx->key->conf.alg != ALG_TKIP ||
            !(rx->fc & IEEE80211_FCTL_PROTECTED) || !WLAN_FC_DATA_PRESENT(fc))
                return TXRX_CONTINUE;
 
-       if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
-           (rx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
-               if (rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) {
-                       if (skb->len < MICHAEL_MIC_LEN)
-                               return TXRX_DROP;
-               }
-               /* Need to verify Michael MIC sometimes in software even when
-                * hwaccel is used. Atheros ar5212: fragmented frames and QoS
-                * frames. */
-               if (!(rx->flags & IEEE80211_TXRXD_FRAGMENTED) && !wpa_test)
-                       goto remove_mic;
-       }
-
        if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len)
            || data_len < MICHAEL_MIC_LEN)
                return TXRX_DROP;
@@ -184,7 +171,6 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx)
                return TXRX_DROP;
        }
 
- remove_mic:
        /* remove Michael MIC from payload */
        skb_trim(skb, skb->len - MICHAEL_MIC_LEN);
 
@@ -287,7 +273,7 @@ ieee80211_tx_h_tkip_encrypt(struct ieee80211_txrx_data *tx)
        ieee80211_tx_set_iswep(tx);
 
        if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
-           !(tx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) &&
+           !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
            !wpa_test) {
                /* hwaccel - with no need for preallocated room for IV/ICV */
                tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx;
@@ -330,11 +316,13 @@ ieee80211_rx_h_tkip_decrypt(struct ieee80211_txrx_data *rx)
        if (!rx->sta || skb->len - hdrlen < 12)
                return TXRX_DROP;
 
-       if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
-           (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
-               if (!(rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV)) {
-                       /* Hardware takes care of all processing, including
-                        * replay protection, so no need to continue here. */
+       if (rx->u.rx.status->flag & RX_FLAG_DECRYPTED) {
+               if (rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED) {
+                       /*
+                        * Hardware took care of all processing, including
+                        * replay protection, and stripped the ICV/IV so
+                        * we cannot do any checks here.
+                        */
                        return TXRX_CONTINUE;
                }
 
@@ -538,7 +526,7 @@ ieee80211_tx_h_ccmp_encrypt(struct ieee80211_txrx_data *tx)
        ieee80211_tx_set_iswep(tx);
 
        if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
-           !(tx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV)) {
+           !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
                /* hwaccel - with no need for preallocated room for CCMP "
                 * header or MIC fields */
                tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx;
@@ -585,8 +573,7 @@ ieee80211_rx_h_ccmp_decrypt(struct ieee80211_txrx_data *rx)
                return TXRX_DROP;
 
        if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
-           (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
-           !(rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV))
+           (rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED))
                return TXRX_CONTINUE;
 
        (void) ccmp_hdr2pn(pn, skb->data + hdrlen);
@@ -605,10 +592,8 @@ ieee80211_rx_h_ccmp_decrypt(struct ieee80211_txrx_data *rx)
                return TXRX_DROP;
        }
 
-       if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
-           (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
-               /* hwaccel has already decrypted frame and verified MIC */
-       } else {
+       if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED)) {
+               /* hardware didn't decrypt/verify MIC */
                u8 *scratch, *b_0, *aad;
 
                scratch = key->u.ccmp.rx_crypto_buf;