aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2x00crypto.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00crypto.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00crypto.c68
1 files changed, 42 insertions, 26 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
index ae31581372c0..57ab42cfed34 100644
--- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -65,7 +65,7 @@ void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry,
65 __set_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags); 65 __set_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags);
66 66
67 txdesc->key_idx = hw_key->hw_key_idx; 67 txdesc->key_idx = hw_key->hw_key_idx;
68 txdesc->iv_offset = ieee80211_get_hdrlen_from_skb(entry->skb); 68 txdesc->iv_offset = txdesc->header_length;
69 txdesc->iv_len = hw_key->iv_len; 69 txdesc->iv_len = hw_key->iv_len;
70 70
71 if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) 71 if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV))
@@ -132,17 +132,16 @@ void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, struct txentry_desc *txdesc)
132 skb_pull(skb, txdesc->iv_len); 132 skb_pull(skb, txdesc->iv_len);
133 133
134 /* IV/EIV data has officially be stripped */ 134 /* IV/EIV data has officially be stripped */
135 skbdesc->flags |= FRAME_DESC_IV_STRIPPED; 135 skbdesc->flags |= SKBDESC_IV_STRIPPED;
136} 136}
137 137
138void rt2x00crypto_tx_insert_iv(struct sk_buff *skb) 138void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length)
139{ 139{
140 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); 140 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
141 unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb);
142 const unsigned int iv_len = 141 const unsigned int iv_len =
143 ((!!(skbdesc->iv[0])) * 4) + ((!!(skbdesc->iv[1])) * 4); 142 ((!!(skbdesc->iv[0])) * 4) + ((!!(skbdesc->iv[1])) * 4);
144 143
145 if (!(skbdesc->flags & FRAME_DESC_IV_STRIPPED)) 144 if (!(skbdesc->flags & SKBDESC_IV_STRIPPED))
146 return; 145 return;
147 146
148 skb_push(skb, iv_len); 147 skb_push(skb, iv_len);
@@ -154,14 +153,15 @@ void rt2x00crypto_tx_insert_iv(struct sk_buff *skb)
154 memcpy(skb->data + header_length, skbdesc->iv, iv_len); 153 memcpy(skb->data + header_length, skbdesc->iv, iv_len);
155 154
156 /* IV/EIV data has returned into the frame */ 155 /* IV/EIV data has returned into the frame */
157 skbdesc->flags &= ~FRAME_DESC_IV_STRIPPED; 156 skbdesc->flags &= ~SKBDESC_IV_STRIPPED;
158} 157}
159 158
160void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align, 159void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad,
161 unsigned int header_length, 160 unsigned int header_length,
162 struct rxdone_entry_desc *rxdesc) 161 struct rxdone_entry_desc *rxdesc)
163{ 162{
164 unsigned int payload_len = rxdesc->size - header_length; 163 unsigned int payload_len = rxdesc->size - header_length;
164 unsigned int align = ALIGN_SIZE(skb, header_length);
165 unsigned int iv_len; 165 unsigned int iv_len;
166 unsigned int icv_len; 166 unsigned int icv_len;
167 unsigned int transfer = 0; 167 unsigned int transfer = 0;
@@ -191,32 +191,48 @@ void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align,
191 } 191 }
192 192
193 /* 193 /*
194 * Make room for new data, note that we increase both 194 * Make room for new data. There are 2 possibilities
195 * headsize and tailsize when required. The tailsize is 195 * either the alignment is already present between
196 * only needed when ICV data needs to be inserted and 196 * the 802.11 header and payload. In that case we
197 * the padding is smaller than the ICV data. 197 * we have to move the header less then the iv_len
198 * When alignment requirements is greater than the 198 * since we can use the already available l2pad bytes
199 * ICV data we must trim the skb to the correct size 199 * for the iv data.
200 * because we need to remove the extra bytes. 200 * When the alignment must be added manually we must
201 * move the header more then iv_len since we must
202 * make room for the payload move as well.
201 */ 203 */
202 skb_push(skb, iv_len + align); 204 if (l2pad) {
203 if (align < icv_len) 205 skb_push(skb, iv_len - align);
204 skb_put(skb, icv_len - align); 206 skb_put(skb, icv_len);
205 else if (align > icv_len)
206 skb_trim(skb, rxdesc->size + iv_len + icv_len);
207 207
208 /* Move ieee80211 header */ 208 /* Move ieee80211 header */
209 memmove(skb->data + transfer, 209 memmove(skb->data + transfer,
210 skb->data + transfer + iv_len + align, 210 skb->data + transfer + (iv_len - align),
211 header_length); 211 header_length);
212 transfer += header_length; 212 transfer += header_length;
213 } else {
214 skb_push(skb, iv_len + align);
215 if (align < icv_len)
216 skb_put(skb, icv_len - align);
217 else if (align > icv_len)
218 skb_trim(skb, rxdesc->size + iv_len + icv_len);
219
220 /* Move ieee80211 header */
221 memmove(skb->data + transfer,
222 skb->data + transfer + iv_len + align,
223 header_length);
224 transfer += header_length;
225 }
213 226
214 /* Copy IV/EIV data */ 227 /* Copy IV/EIV data */
215 memcpy(skb->data + transfer, rxdesc->iv, iv_len); 228 memcpy(skb->data + transfer, rxdesc->iv, iv_len);
216 transfer += iv_len; 229 transfer += iv_len;
217 230
218 /* Move payload */ 231 /*
219 if (align) { 232 * Move payload for alignment purposes. Note that
233 * this is only needed when no l2 padding is present.
234 */
235 if (!l2pad) {
220 memmove(skb->data + transfer, 236 memmove(skb->data + transfer,
221 skb->data + transfer + align, 237 skb->data + transfer + align,
222 payload_len); 238 payload_len);