diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ieee80211/ieee80211_crypt_wep.c | 61 | ||||
-rw-r--r-- | net/ieee80211/ieee80211_tx.c | 2 | ||||
-rw-r--r-- | net/ieee80211/ieee80211_wx.c | 2 |
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, | 79 | static 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 | */ | ||
84 | static 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 | */ | ||
121 | static 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 | ||