aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2005-12-31 05:35:20 -0500
committerJeff Garzik <jgarzik@pobox.com>2006-01-09 10:34:25 -0500
commita4bf26f30e398afa293b85103c885f03d4660a07 (patch)
treeba3db16dc30725c1c1009831b9a29de00d3fd238 /net/ieee80211
parentdf22b8aaba3f41cc61f57f5ead78be45edcb7db5 (diff)
[PATCH] ieee80211: enable hw wep where host has to build IV
This patch fixes some of the ieee80211 crypto related code so that instead of having the host fully do crypto operations, the host_build_iv flag works properly (for WEP in this patch) which, if turned on, requires the hardware to do all crypto operations, but the ieee80211 layer builds the IV. The hardware also has to build the ICV. Previously, the host_build_iv flag couldn't be used at all for WEP, and not alone (with both host_decrypt and host_encrypt disabled) because the crypto algorithm wasn't assigned. This is also fixed. I have tested this patch both in host crypto mode and in hw crypto mode (with the Broadcom chipset). [resent, signing digitally caused it to be MIME-junked, sorry] Signed-Off-By: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'net/ieee80211')
-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