aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/wep.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/wep.c')
-rw-r--r--net/mac80211/wep.c52
1 files changed, 23 insertions, 29 deletions
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
index ef73105b3061..8a980f136941 100644
--- a/net/mac80211/wep.c
+++ b/net/mac80211/wep.c
@@ -67,10 +67,10 @@ static inline bool ieee80211_wep_weak_iv(u32 iv, int keylen)
67 67
68 68
69static void ieee80211_wep_get_iv(struct ieee80211_local *local, 69static void ieee80211_wep_get_iv(struct ieee80211_local *local,
70 struct ieee80211_key *key, u8 *iv) 70 int keylen, int keyidx, u8 *iv)
71{ 71{
72 local->wep_iv++; 72 local->wep_iv++;
73 if (ieee80211_wep_weak_iv(local->wep_iv, key->conf.keylen)) 73 if (ieee80211_wep_weak_iv(local->wep_iv, keylen))
74 local->wep_iv += 0x0100; 74 local->wep_iv += 0x0100;
75 75
76 if (!iv) 76 if (!iv)
@@ -79,13 +79,13 @@ static void ieee80211_wep_get_iv(struct ieee80211_local *local,
79 *iv++ = (local->wep_iv >> 16) & 0xff; 79 *iv++ = (local->wep_iv >> 16) & 0xff;
80 *iv++ = (local->wep_iv >> 8) & 0xff; 80 *iv++ = (local->wep_iv >> 8) & 0xff;
81 *iv++ = local->wep_iv & 0xff; 81 *iv++ = local->wep_iv & 0xff;
82 *iv++ = key->conf.keyidx << 6; 82 *iv++ = keyidx << 6;
83} 83}
84 84
85 85
86static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local, 86static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local,
87 struct sk_buff *skb, 87 struct sk_buff *skb,
88 struct ieee80211_key *key) 88 int keylen, int keyidx)
89{ 89{
90 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 90 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
91 unsigned int hdrlen; 91 unsigned int hdrlen;
@@ -100,7 +100,7 @@ static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local,
100 hdrlen = ieee80211_hdrlen(hdr->frame_control); 100 hdrlen = ieee80211_hdrlen(hdr->frame_control);
101 newhdr = skb_push(skb, WEP_IV_LEN); 101 newhdr = skb_push(skb, WEP_IV_LEN);
102 memmove(newhdr, newhdr + WEP_IV_LEN, hdrlen); 102 memmove(newhdr, newhdr + WEP_IV_LEN, hdrlen);
103 ieee80211_wep_get_iv(local, key, newhdr + hdrlen); 103 ieee80211_wep_get_iv(local, keylen, keyidx, newhdr + hdrlen);
104 return newhdr + hdrlen; 104 return newhdr + hdrlen;
105} 105}
106 106
@@ -144,26 +144,17 @@ void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
144 * 144 *
145 * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data)) 145 * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
146 */ 146 */
147int ieee80211_wep_encrypt(struct ieee80211_local *local, struct sk_buff *skb, 147int ieee80211_wep_encrypt(struct ieee80211_local *local,
148 struct ieee80211_key *key) 148 struct sk_buff *skb,
149 const u8 *key, int keylen, int keyidx)
149{ 150{
150 u32 klen; 151 u8 *iv;
151 u8 *rc4key, *iv;
152 size_t len; 152 size_t len;
153 u8 rc4key[3 + WLAN_KEY_LEN_WEP104];
153 154
154 if (!key || key->conf.alg != ALG_WEP) 155 iv = ieee80211_wep_add_iv(local, skb, keylen, keyidx);
155 return -1; 156 if (!iv)
156
157 klen = 3 + key->conf.keylen;
158 rc4key = kmalloc(klen, GFP_ATOMIC);
159 if (!rc4key)
160 return -1;
161
162 iv = ieee80211_wep_add_iv(local, skb, key);
163 if (!iv) {
164 kfree(rc4key);
165 return -1; 157 return -1;
166 }
167 158
168 len = skb->len - (iv + WEP_IV_LEN - skb->data); 159 len = skb->len - (iv + WEP_IV_LEN - skb->data);
169 160
@@ -171,16 +162,14 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local, struct sk_buff *skb,
171 memcpy(rc4key, iv, 3); 162 memcpy(rc4key, iv, 3);
172 163
173 /* Copy rest of the WEP key (the secret part) */ 164 /* Copy rest of the WEP key (the secret part) */
174 memcpy(rc4key + 3, key->conf.key, key->conf.keylen); 165 memcpy(rc4key + 3, key, keylen);
175 166
176 /* Add room for ICV */ 167 /* Add room for ICV */
177 skb_put(skb, WEP_ICV_LEN); 168 skb_put(skb, WEP_ICV_LEN);
178 169
179 ieee80211_wep_encrypt_data(local->wep_tx_tfm, rc4key, klen, 170 ieee80211_wep_encrypt_data(local->wep_tx_tfm, rc4key, keylen + 3,
180 iv + WEP_IV_LEN, len); 171 iv + WEP_IV_LEN, len);
181 172
182 kfree(rc4key);
183
184 return 0; 173 return 0;
185} 174}
186 175
@@ -216,8 +205,9 @@ int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
216 * failure. If frame is OK, IV and ICV will be removed, i.e., decrypted payload 205 * failure. If frame is OK, IV and ICV will be removed, i.e., decrypted payload
217 * is moved to the beginning of the skb and skb length will be reduced. 206 * is moved to the beginning of the skb and skb length will be reduced.
218 */ 207 */
219int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb, 208static int ieee80211_wep_decrypt(struct ieee80211_local *local,
220 struct ieee80211_key *key) 209 struct sk_buff *skb,
210 struct ieee80211_key *key)
221{ 211{
222 u32 klen; 212 u32 klen;
223 u8 *rc4key; 213 u8 *rc4key;
@@ -314,12 +304,16 @@ static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
314 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 304 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
315 305
316 if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { 306 if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
317 if (ieee80211_wep_encrypt(tx->local, skb, tx->key)) 307 if (ieee80211_wep_encrypt(tx->local, skb, tx->key->conf.key,
308 tx->key->conf.keylen,
309 tx->key->conf.keyidx))
318 return -1; 310 return -1;
319 } else { 311 } else {
320 info->control.hw_key = &tx->key->conf; 312 info->control.hw_key = &tx->key->conf;
321 if (tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) { 313 if (tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) {
322 if (!ieee80211_wep_add_iv(tx->local, skb, tx->key)) 314 if (!ieee80211_wep_add_iv(tx->local, skb,
315 tx->key->conf.keylen,
316 tx->key->conf.keyidx))
323 return -1; 317 return -1;
324 } 318 }
325 } 319 }