Commit 077a9154 authored by Arik Nemtsov's avatar Arik Nemtsov Committed by John W. Linville

mac80211: support adding IV-room in the skb for CCMP keys

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: default avatarArik Nemtsov <arik@wizery.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 3b7b72ee
...@@ -901,6 +901,10 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) ...@@ -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 * @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 * CCMP key if it requires CCMP encryption of management frames (MFP) to
* be done in software. * 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 { enum ieee80211_key_flags {
IEEE80211_KEY_FLAG_WMM_STA = 1<<0, IEEE80211_KEY_FLAG_WMM_STA = 1<<0,
...@@ -908,6 +912,7 @@ enum ieee80211_key_flags { ...@@ -908,6 +912,7 @@ enum ieee80211_key_flags {
IEEE80211_KEY_FLAG_GENERATE_MMIC= 1<<2, IEEE80211_KEY_FLAG_GENERATE_MMIC= 1<<2,
IEEE80211_KEY_FLAG_PAIRWISE = 1<<3, IEEE80211_KEY_FLAG_PAIRWISE = 1<<3,
IEEE80211_KEY_FLAG_SW_MGMT = 1<<4, IEEE80211_KEY_FLAG_SW_MGMT = 1<<4,
IEEE80211_KEY_FLAG_PUT_IV_SPACE = 1<<5,
}; };
/** /**
......
...@@ -133,9 +133,13 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) ...@@ -133,9 +133,13 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || 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--; 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; return 0;
} }
...@@ -178,7 +182,8 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) ...@@ -178,7 +182,8 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
sdata = key->sdata; sdata = key->sdata;
if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || 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); increment_tailroom_need_count(sdata);
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
......
...@@ -390,7 +390,8 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) ...@@ -390,7 +390,8 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
u8 scratch[6 * AES_BLOCK_SIZE]; u8 scratch[6 * AES_BLOCK_SIZE];
if (info->control.hw_key && 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 * hwaccel has no need for preallocated room for CCMP
* header or MIC fields * header or MIC fields
...@@ -412,6 +413,11 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) ...@@ -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); pos = skb_push(skb, CCMP_HDR_LEN);
memmove(pos, pos + CCMP_HDR_LEN, hdrlen); 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; hdr = (struct ieee80211_hdr *) pos;
pos += hdrlen; pos += hdrlen;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment