diff options
Diffstat (limited to 'net/mac80211/wep.c')
-rw-r--r-- | net/mac80211/wep.c | 52 |
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 | ||
69 | static void ieee80211_wep_get_iv(struct ieee80211_local *local, | 69 | static 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 | ||
86 | static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local, | 86 | static 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 | */ |
147 | int ieee80211_wep_encrypt(struct ieee80211_local *local, struct sk_buff *skb, | 147 | int 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 | */ |
219 | int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb, | 208 | static 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 | } |