aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ieee80211/ieee80211_crypt_wep.c61
-rw-r--r--net/ieee80211/ieee80211_tx.c2
-rw-r--r--net/ieee80211/ieee80211_wx.c2
3 files changed, 45 insertions, 20 deletions
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c
index 073aebdf0f67..f8dca31be5dd 100644
--- a/net/ieee80211/ieee80211_crypt_wep.c
+++ b/net/ieee80211/ieee80211_crypt_wep.c
@@ -75,22 +75,14 @@ static void prism2_wep_deinit(void *priv)
75 kfree(priv); 75 kfree(priv);
76} 76}
77 77
78/* Perform WEP encryption on given skb that has at least 4 bytes of headroom 78/* Add WEP IV/key info to a frame that has at least 4 bytes of headroom */
79 * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted, 79static int prism2_wep_build_iv(struct sk_buff *skb, int hdr_len, void *priv)
80 * so the payload length increases with 8 bytes.
81 *
82 * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
83 */
84static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
85{ 80{
86 struct prism2_wep_data *wep = priv; 81 struct prism2_wep_data *wep = priv;
87 u32 crc, klen, len; 82 u32 klen, len;
88 u8 key[WEP_KEY_LEN + 3]; 83 u8 *pos;
89 u8 *pos, *icv; 84
90 struct scatterlist sg; 85 if (skb_headroom(skb) < 4 || skb->len < hdr_len)
91
92 if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 ||
93 skb->len < hdr_len)
94 return -1; 86 return -1;
95 87
96 len = skb->len - hdr_len; 88 len = skb->len - hdr_len;
@@ -112,15 +104,47 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
112 } 104 }
113 105
114 /* Prepend 24-bit IV to RC4 key and TX frame */ 106 /* Prepend 24-bit IV to RC4 key and TX frame */
115 *pos++ = key[0] = (wep->iv >> 16) & 0xff; 107 *pos++ = (wep->iv >> 16) & 0xff;
116 *pos++ = key[1] = (wep->iv >> 8) & 0xff; 108 *pos++ = (wep->iv >> 8) & 0xff;
117 *pos++ = key[2] = wep->iv & 0xff; 109 *pos++ = wep->iv & 0xff;
118 *pos++ = wep->key_idx << 6; 110 *pos++ = wep->key_idx << 6;
119 111
112 return 0;
113}
114
115/* Perform WEP encryption on given skb that has at least 4 bytes of headroom
116 * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted,
117 * so the payload length increases with 8 bytes.
118 *
119 * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
120 */
121static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
122{
123 struct prism2_wep_data *wep = priv;
124 u32 crc, klen, len;
125 u8 *pos, *icv;
126 struct scatterlist sg;
127 u8 key[WEP_KEY_LEN + 3];
128
129 /* other checks are in prism2_wep_build_iv */
130 if (skb_tailroom(skb) < 4)
131 return -1;
132
133 /* add the IV to the frame */
134 if (prism2_wep_build_iv(skb, hdr_len, priv))
135 return -1;
136
137 /* Copy the IV into the first 3 bytes of the key */
138 memcpy(key, skb->data + hdr_len, 3);
139
120 /* Copy rest of the WEP key (the secret part) */ 140 /* Copy rest of the WEP key (the secret part) */
121 memcpy(key + 3, wep->key, wep->key_len); 141 memcpy(key + 3, wep->key, wep->key_len);
142
143 len = skb->len - hdr_len - 4;
144 pos = skb->data + hdr_len + 4;
145 klen = 3 + wep->key_len;
122 146
123 /* Append little-endian CRC32 and encrypt it to produce ICV */ 147 /* Append little-endian CRC32 over only the data and encrypt it to produce ICV */
124 crc = ~crc32_le(~0, pos, len); 148 crc = ~crc32_le(~0, pos, len);
125 icv = skb_put(skb, 4); 149 icv = skb_put(skb, 4);
126 icv[0] = crc; 150 icv[0] = crc;
@@ -231,6 +255,7 @@ static struct ieee80211_crypto_ops ieee80211_crypt_wep = {
231 .name = "WEP", 255 .name = "WEP",
232 .init = prism2_wep_init, 256 .init = prism2_wep_init,
233 .deinit = prism2_wep_deinit, 257 .deinit = prism2_wep_deinit,
258 .build_iv = prism2_wep_build_iv,
234 .encrypt_mpdu = prism2_wep_encrypt, 259 .encrypt_mpdu = prism2_wep_encrypt,
235 .decrypt_mpdu = prism2_wep_decrypt, 260 .decrypt_mpdu = prism2_wep_decrypt,
236 .encrypt_msdu = NULL, 261 .encrypt_msdu = NULL,
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index 445f206e65e0..e5b33c8d5dbc 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -288,7 +288,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
288 /* Determine total amount of storage required for TXB packets */ 288 /* Determine total amount of storage required for TXB packets */
289 bytes = skb->len + SNAP_SIZE + sizeof(u16); 289 bytes = skb->len + SNAP_SIZE + sizeof(u16);
290 290
291 if (host_encrypt) 291 if (host_encrypt || host_build_iv)
292 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA | 292 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
293 IEEE80211_FCTL_PROTECTED; 293 IEEE80211_FCTL_PROTECTED;
294 else 294 else
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index 181755f2aa8b..406d5b964905 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -284,7 +284,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
284 }; 284 };
285 int i, key, key_provided, len; 285 int i, key, key_provided, len;
286 struct ieee80211_crypt_data **crypt; 286 struct ieee80211_crypt_data **crypt;
287 int host_crypto = ieee->host_encrypt || ieee->host_decrypt; 287 int host_crypto = ieee->host_encrypt || ieee->host_decrypt || ieee->host_build_iv;
288 288
289 IEEE80211_DEBUG_WX("SET_ENCODE\n"); 289 IEEE80211_DEBUG_WX("SET_ENCODE\n");
290 290