mac80211: support adding IV-room in the skb for CCMP keys
authorArik Nemtsov <arik@wizery.com>
Sun, 23 Oct 2011 06:21:41 +0000 (08:21 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 8 Nov 2011 20:54:27 +0000 (15:54 -0500)
Some cards can generate CCMP IVs in HW, but require the space for the IV
to be pre-allocated in the frame at the correct offset. Add a key flag
that allows us to achieve this.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
include/net/mac80211.h
net/mac80211/key.c
net/mac80211/wpa.c

index dc1123aa8181d08a9b91bf2fe3281577088e56d1..f4e0ab49db202c5144e53953bca14850ef8e51a1 100644 (file)
@@ -901,6 +901,10 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
  * @IEEE80211_KEY_FLAG_SW_MGMT: This flag should be set by the driver for a
  *     CCMP key if it requires CCMP encryption of management frames (MFP) to
  *     be done in software.
+ * @IEEE80211_KEY_FLAG_PUT_IV_SPACE: This flag should be set by the driver
+ *     for a CCMP key if space should be prepared for the IV, but the IV
+ *     itself should not be generated. Do not set together with
+ *     @IEEE80211_KEY_FLAG_GENERATE_IV on the same key.
  */
 enum ieee80211_key_flags {
        IEEE80211_KEY_FLAG_WMM_STA      = 1<<0,
@@ -908,6 +912,7 @@ enum ieee80211_key_flags {
        IEEE80211_KEY_FLAG_GENERATE_MMIC= 1<<2,
        IEEE80211_KEY_FLAG_PAIRWISE     = 1<<3,
        IEEE80211_KEY_FLAG_SW_MGMT      = 1<<4,
+       IEEE80211_KEY_FLAG_PUT_IV_SPACE = 1<<5,
 };
 
 /**
index 756b157c2edd7a147c9390ec773d173f074117d5..17a5220ed4504ae3752acb9fca22bef7da1b1940 100644 (file)
@@ -133,9 +133,13 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
                key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
 
                if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
-                     (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
+                     (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) ||
+                     (key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)))
                        sdata->crypto_tx_tailroom_needed_cnt--;
 
+               WARN_ON((key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) &&
+                       (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV));
+
                return 0;
        }
 
@@ -178,7 +182,8 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
        sdata = key->sdata;
 
        if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
-             (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
+             (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) ||
+             (key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)))
                increment_tailroom_need_count(sdata);
 
        if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
index f614ce7bb6e3b4aea4f9c445e2594b2c6366e6d0..13efab5bf12aa00ce34fece5d8fa2734efdb1a0a 100644 (file)
@@ -390,7 +390,8 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
        u8 scratch[6 * AES_BLOCK_SIZE];
 
        if (info->control.hw_key &&
-           !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
+           !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
+           !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) {
                /*
                 * hwaccel has no need for preallocated room for CCMP
                 * header or MIC fields
@@ -412,6 +413,11 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 
        pos = skb_push(skb, CCMP_HDR_LEN);
        memmove(pos, pos + CCMP_HDR_LEN, hdrlen);
+
+       /* the HW only needs room for the IV, but not the actual IV */
+       if (info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)
+               return 0;
+
        hdr = (struct ieee80211_hdr *) pos;
        pos += hdrlen;