diff options
Diffstat (limited to 'net/ieee80211/ieee80211_crypt_wep.c')
-rw-r--r-- | net/ieee80211/ieee80211_crypt_wep.c | 61 |
1 files changed, 43 insertions, 18 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, |