diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00crypto.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00crypto.c | 87 |
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 | ||
106 | void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, unsigned int iv_len) | 107 | void 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 | ||
118 | void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, unsigned int iv_len) | 118 | void 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 | ||
139 | void rt2x00crypto_tx_insert_iv(struct sk_buff *skb) | 138 | void 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 | ||
161 | void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align, | 159 | void 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); |