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.c87
1 files changed, 51 insertions, 36 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
index 0b41845d9543..57ab42cfed34 100644
--- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -65,7 +65,8 @@ 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 70
70 if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) 71 if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV))
71 __set_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags); 72 __set_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags);
@@ -103,47 +104,44 @@ unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,
103 return overhead; 104 return overhead;
104} 105}
105 106
106void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, unsigned int iv_len) 107void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, struct txentry_desc *txdesc)
107{ 108{
108 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); 109 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
109 unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb);
110 110
111 if (unlikely(!iv_len)) 111 if (unlikely(!txdesc->iv_len))
112 return; 112 return;
113 113
114 /* Copy IV/EIV data */ 114 /* Copy IV/EIV data */
115 memcpy(skbdesc->iv, skb->data + header_length, iv_len); 115 memcpy(skbdesc->iv, skb->data + txdesc->iv_offset, txdesc->iv_len);
116} 116}
117 117
118void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, unsigned int iv_len) 118void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, struct txentry_desc *txdesc)
119{ 119{
120 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); 120 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
121 unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb);
122 121
123 if (unlikely(!iv_len)) 122 if (unlikely(!txdesc->iv_len))
124 return; 123 return;
125 124
126 /* Copy IV/EIV data */ 125 /* Copy IV/EIV data */
127 memcpy(skbdesc->iv, skb->data + header_length, iv_len); 126 memcpy(skbdesc->iv, skb->data + txdesc->iv_offset, txdesc->iv_len);
128 127
129 /* Move ieee80211 header */ 128 /* Move ieee80211 header */
130 memmove(skb->data + iv_len, skb->data, header_length); 129 memmove(skb->data + txdesc->iv_len, skb->data, txdesc->iv_offset);
131 130
132 /* Pull buffer to correct size */ 131 /* Pull buffer to correct size */
133 skb_pull(skb, iv_len); 132 skb_pull(skb, txdesc->iv_len);
134 133
135 /* IV/EIV data has officially be stripped */ 134 /* IV/EIV data has officially be stripped */
136 skbdesc->flags |= FRAME_DESC_IV_STRIPPED; 135 skbdesc->flags |= SKBDESC_IV_STRIPPED;
137} 136}
138 137
139void rt2x00crypto_tx_insert_iv(struct sk_buff *skb) 138void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length)
140{ 139{
141 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); 140 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
142 unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb);
143 const unsigned int iv_len = 141 const unsigned int iv_len =
144 ((!!(skbdesc->iv[0])) * 4) + ((!!(skbdesc->iv[1])) * 4); 142 ((!!(skbdesc->iv[0])) * 4) + ((!!(skbdesc->iv[1])) * 4);
145 143
146 if (!(skbdesc->flags & FRAME_DESC_IV_STRIPPED)) 144 if (!(skbdesc->flags & SKBDESC_IV_STRIPPED))
147 return; 145 return;
148 146
149 skb_push(skb, iv_len); 147 skb_push(skb, iv_len);
@@ -155,14 +153,15 @@ void rt2x00crypto_tx_insert_iv(struct sk_buff *skb)
155 memcpy(skb->data + header_length, skbdesc->iv, iv_len); 153 memcpy(skb->data + header_length, skbdesc->iv, iv_len);
156 154
157 /* IV/EIV data has returned into the frame */ 155 /* IV/EIV data has returned into the frame */
158 skbdesc->flags &= ~FRAME_DESC_IV_STRIPPED; 156 skbdesc->flags &= ~SKBDESC_IV_STRIPPED;
159} 157}
160 158
161void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align, 159void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad,
162 unsigned int header_length, 160 unsigned int header_length,
163 struct rxdone_entry_desc *rxdesc) 161 struct rxdone_entry_desc *rxdesc)
164{ 162{
165 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);
166 unsigned int iv_len; 165 unsigned int iv_len;
167 unsigned int icv_len; 166 unsigned int icv_len;
168 unsigned int transfer = 0; 167 unsigned int transfer = 0;
@@ -192,32 +191,48 @@ void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align,
192 } 191 }
193 192
194 /* 193 /*
195 * Make room for new data, note that we increase both 194 * Make room for new data. There are 2 possibilities
196 * headsize and tailsize when required. The tailsize is 195 * either the alignment is already present between
197 * only needed when ICV data needs to be inserted and 196 * the 802.11 header and payload. In that case we
198 * the padding is smaller than the ICV data. 197 * we have to move the header less then the iv_len
199 * When alignment requirements is greater than the 198 * since we can use the already available l2pad bytes
200 * ICV data we must trim the skb to the correct size 199 * for the iv data.
201 * 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.
202 */ 203 */
203 skb_push(skb, iv_len + align); 204 if (l2pad) {
204 if (align < icv_len) 205 skb_push(skb, iv_len - align);
205 skb_put(skb, icv_len - align); 206 skb_put(skb, icv_len);
206 else if (align > icv_len)
207 skb_trim(skb, rxdesc->size + iv_len + icv_len);
208 207
209 /* Move ieee80211 header */ 208 /* Move ieee80211 header */
210 memmove(skb->data + transfer, 209 memmove(skb->data + transfer,
211 skb->data + transfer + iv_len + align, 210 skb->data + transfer + (iv_len - align),
212 header_length); 211 header_length);
213 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 }
214 226
215 /* Copy IV/EIV data */ 227 /* Copy IV/EIV data */
216 memcpy(skb->data + transfer, rxdesc->iv, iv_len); 228 memcpy(skb->data + transfer, rxdesc->iv, iv_len);
217 transfer += iv_len; 229 transfer += iv_len;
218 230
219 /* Move payload */ 231 /*
220 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) {
221 memmove(skb->data + transfer, 236 memmove(skb->data + transfer,
222 skb->data + transfer + align, 237 skb->data + transfer + align,
223 payload_len); 238 payload_len);