Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Johannes Berg and committed by
Jeff Garzik
a4bf26f3 df22b8aa

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