diff options
author | David Kilroy <kilroyd@googlemail.com> | 2009-08-05 16:23:32 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-08-14 09:12:45 -0400 |
commit | 4af198fb7a99b07980b1bd52df550ba3f24688df (patch) | |
tree | 8955b89e70dbf82bcf7537130f43a8a1ab2350e3 /drivers/net/wireless/orinoco/wext.c | |
parent | 2b2603515e26466685895e93cae59bc061389f11 (diff) |
orinoco: consolidate storage of WEP and TKIP keys
When TKIP support was added, we stored the keys separately to avoid
issues when both TKIP and WEP keys are sent to the driver.
We need to consolidate the storage to convert to cfg80211, so do this
first and try iron out the issues.
Signed-off-by: David Kilroy <kilroyd@googlemail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/orinoco/wext.c')
-rw-r--r-- | drivers/net/wireless/orinoco/wext.c | 122 |
1 files changed, 81 insertions, 41 deletions
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c index f68bbe383e0f..3e56f7643df5 100644 --- a/drivers/net/wireless/orinoco/wext.c +++ b/drivers/net/wireless/orinoco/wext.c | |||
@@ -22,6 +22,67 @@ | |||
22 | 22 | ||
23 | #define MAX_RID_LEN 1024 | 23 | #define MAX_RID_LEN 1024 |
24 | 24 | ||
25 | /* Helper routine to record keys | ||
26 | * Do not call from interrupt context */ | ||
27 | static int orinoco_set_key(struct orinoco_private *priv, int index, | ||
28 | enum orinoco_alg alg, const u8 *key, int key_len, | ||
29 | const u8 *seq, int seq_len) | ||
30 | { | ||
31 | kzfree(priv->keys[index].key); | ||
32 | kzfree(priv->keys[index].seq); | ||
33 | |||
34 | if (key_len) { | ||
35 | priv->keys[index].key = kzalloc(key_len, GFP_KERNEL); | ||
36 | if (!priv->keys[index].key) | ||
37 | goto nomem; | ||
38 | } else | ||
39 | priv->keys[index].key = NULL; | ||
40 | |||
41 | if (seq_len) { | ||
42 | priv->keys[index].seq = kzalloc(seq_len, GFP_KERNEL); | ||
43 | if (!priv->keys[index].seq) | ||
44 | goto free_key; | ||
45 | } else | ||
46 | priv->keys[index].seq = NULL; | ||
47 | |||
48 | priv->keys[index].key_len = key_len; | ||
49 | priv->keys[index].seq_len = seq_len; | ||
50 | |||
51 | if (key_len) | ||
52 | memcpy(priv->keys[index].key, key, key_len); | ||
53 | if (seq_len) | ||
54 | memcpy(priv->keys[index].seq, seq, seq_len); | ||
55 | |||
56 | switch (alg) { | ||
57 | case ORINOCO_ALG_TKIP: | ||
58 | priv->keys[index].cipher = WLAN_CIPHER_SUITE_TKIP; | ||
59 | break; | ||
60 | |||
61 | case ORINOCO_ALG_WEP: | ||
62 | priv->keys[index].cipher = (key_len > SMALL_KEY_SIZE) ? | ||
63 | WLAN_CIPHER_SUITE_WEP104 : WLAN_CIPHER_SUITE_WEP40; | ||
64 | break; | ||
65 | |||
66 | case ORINOCO_ALG_NONE: | ||
67 | default: | ||
68 | priv->keys[index].cipher = 0; | ||
69 | break; | ||
70 | } | ||
71 | |||
72 | return 0; | ||
73 | |||
74 | free_key: | ||
75 | kfree(priv->keys[index].key); | ||
76 | priv->keys[index].key = NULL; | ||
77 | |||
78 | nomem: | ||
79 | priv->keys[index].key_len = 0; | ||
80 | priv->keys[index].seq_len = 0; | ||
81 | priv->keys[index].cipher = 0; | ||
82 | |||
83 | return -ENOMEM; | ||
84 | } | ||
85 | |||
25 | static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev) | 86 | static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev) |
26 | { | 87 | { |
27 | struct orinoco_private *priv = ndev_priv(dev); | 88 | struct orinoco_private *priv = ndev_priv(dev); |
@@ -180,7 +241,6 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, | |||
180 | int setindex = priv->tx_key; | 241 | int setindex = priv->tx_key; |
181 | enum orinoco_alg encode_alg = priv->encode_alg; | 242 | enum orinoco_alg encode_alg = priv->encode_alg; |
182 | int restricted = priv->wep_restrict; | 243 | int restricted = priv->wep_restrict; |
183 | u16 xlen = 0; | ||
184 | int err = -EINPROGRESS; /* Call commit handler */ | 244 | int err = -EINPROGRESS; /* Call commit handler */ |
185 | unsigned long flags; | 245 | unsigned long flags; |
186 | 246 | ||
@@ -207,12 +267,6 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, | |||
207 | if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) | 267 | if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) |
208 | index = priv->tx_key; | 268 | index = priv->tx_key; |
209 | 269 | ||
210 | /* Adjust key length to a supported value */ | ||
211 | if (erq->length > SMALL_KEY_SIZE) | ||
212 | xlen = LARGE_KEY_SIZE; | ||
213 | else /* (erq->length > 0) */ | ||
214 | xlen = SMALL_KEY_SIZE; | ||
215 | |||
216 | /* Switch on WEP if off */ | 270 | /* Switch on WEP if off */ |
217 | if (encode_alg != ORINOCO_ALG_WEP) { | 271 | if (encode_alg != ORINOCO_ALG_WEP) { |
218 | setindex = index; | 272 | setindex = index; |
@@ -229,7 +283,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, | |||
229 | } | 283 | } |
230 | } else { | 284 | } else { |
231 | /* Set the index : Check that the key is valid */ | 285 | /* Set the index : Check that the key is valid */ |
232 | if (priv->keys[index].len == 0) { | 286 | if (priv->keys[index].key_len == 0) { |
233 | err = -EINVAL; | 287 | err = -EINVAL; |
234 | goto out; | 288 | goto out; |
235 | } | 289 | } |
@@ -245,10 +299,8 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, | |||
245 | restricted = 1; | 299 | restricted = 1; |
246 | 300 | ||
247 | if (erq->pointer && erq->length > 0) { | 301 | if (erq->pointer && erq->length > 0) { |
248 | priv->keys[index].len = cpu_to_le16(xlen); | 302 | err = orinoco_set_key(priv, index, ORINOCO_ALG_WEP, keybuf, |
249 | memset(priv->keys[index].data, 0, | 303 | erq->length, NULL, 0); |
250 | sizeof(priv->keys[index].data)); | ||
251 | memcpy(priv->keys[index].data, keybuf, erq->length); | ||
252 | } | 304 | } |
253 | priv->tx_key = setindex; | 305 | priv->tx_key = setindex; |
254 | 306 | ||
@@ -277,7 +329,6 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev, | |||
277 | { | 329 | { |
278 | struct orinoco_private *priv = ndev_priv(dev); | 330 | struct orinoco_private *priv = ndev_priv(dev); |
279 | int index = (erq->flags & IW_ENCODE_INDEX) - 1; | 331 | int index = (erq->flags & IW_ENCODE_INDEX) - 1; |
280 | u16 xlen = 0; | ||
281 | unsigned long flags; | 332 | unsigned long flags; |
282 | 333 | ||
283 | if (!priv->has_wep) | 334 | if (!priv->has_wep) |
@@ -299,11 +350,9 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev, | |||
299 | else | 350 | else |
300 | erq->flags |= IW_ENCODE_OPEN; | 351 | erq->flags |= IW_ENCODE_OPEN; |
301 | 352 | ||
302 | xlen = le16_to_cpu(priv->keys[index].len); | 353 | erq->length = priv->keys[index].key_len; |
303 | 354 | ||
304 | erq->length = xlen; | 355 | memcpy(keybuf, priv->keys[index].key, erq->length); |
305 | |||
306 | memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE); | ||
307 | 356 | ||
308 | orinoco_unlock(priv, &flags); | 357 | orinoco_unlock(priv, &flags); |
309 | return 0; | 358 | return 0; |
@@ -789,7 +838,6 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev, | |||
789 | int idx, alg = ext->alg, set_key = 1; | 838 | int idx, alg = ext->alg, set_key = 1; |
790 | unsigned long flags; | 839 | unsigned long flags; |
791 | int err = -EINVAL; | 840 | int err = -EINVAL; |
792 | u16 key_len; | ||
793 | 841 | ||
794 | if (orinoco_lock(priv, &flags) != 0) | 842 | if (orinoco_lock(priv, &flags) != 0) |
795 | return -EBUSY; | 843 | return -EBUSY; |
@@ -822,24 +870,17 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev, | |||
822 | switch (alg) { | 870 | switch (alg) { |
823 | case IW_ENCODE_ALG_NONE: | 871 | case IW_ENCODE_ALG_NONE: |
824 | priv->encode_alg = ORINOCO_ALG_NONE; | 872 | priv->encode_alg = ORINOCO_ALG_NONE; |
825 | priv->keys[idx].len = 0; | 873 | err = orinoco_set_key(priv, idx, ORINOCO_ALG_NONE, |
874 | NULL, 0, NULL, 0); | ||
826 | break; | 875 | break; |
827 | 876 | ||
828 | case IW_ENCODE_ALG_WEP: | 877 | case IW_ENCODE_ALG_WEP: |
829 | if (ext->key_len > SMALL_KEY_SIZE) | 878 | if (ext->key_len <= 0) |
830 | key_len = LARGE_KEY_SIZE; | ||
831 | else if (ext->key_len > 0) | ||
832 | key_len = SMALL_KEY_SIZE; | ||
833 | else | ||
834 | goto out; | 879 | goto out; |
835 | 880 | ||
836 | priv->encode_alg = ORINOCO_ALG_WEP; | 881 | priv->encode_alg = ORINOCO_ALG_WEP; |
837 | priv->keys[idx].len = cpu_to_le16(key_len); | 882 | err = orinoco_set_key(priv, idx, ORINOCO_ALG_WEP, |
838 | 883 | ext->key, ext->key_len, NULL, 0); | |
839 | key_len = min(ext->key_len, key_len); | ||
840 | |||
841 | memset(priv->keys[idx].data, 0, ORINOCO_MAX_KEY_SIZE); | ||
842 | memcpy(priv->keys[idx].data, ext->key, key_len); | ||
843 | break; | 884 | break; |
844 | 885 | ||
845 | case IW_ENCODE_ALG_TKIP: | 886 | case IW_ENCODE_ALG_TKIP: |
@@ -847,20 +888,21 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev, | |||
847 | u8 *tkip_iv = NULL; | 888 | u8 *tkip_iv = NULL; |
848 | 889 | ||
849 | if (!priv->has_wpa || | 890 | if (!priv->has_wpa || |
850 | (ext->key_len > sizeof(priv->tkip_key[0]))) | 891 | (ext->key_len > sizeof(struct orinoco_tkip_key))) |
851 | goto out; | 892 | goto out; |
852 | 893 | ||
853 | priv->encode_alg = ORINOCO_ALG_TKIP; | 894 | priv->encode_alg = ORINOCO_ALG_TKIP; |
854 | memset(&priv->tkip_key[idx], 0, | ||
855 | sizeof(priv->tkip_key[idx])); | ||
856 | memcpy(&priv->tkip_key[idx], ext->key, ext->key_len); | ||
857 | 895 | ||
858 | if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) | 896 | if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) |
859 | tkip_iv = &ext->rx_seq[0]; | 897 | tkip_iv = &ext->rx_seq[0]; |
860 | 898 | ||
899 | err = orinoco_set_key(priv, idx, ORINOCO_ALG_TKIP, | ||
900 | ext->key, ext->key_len, tkip_iv, | ||
901 | ORINOCO_SEQ_LEN); | ||
902 | |||
861 | err = __orinoco_hw_set_tkip_key(priv, idx, | 903 | err = __orinoco_hw_set_tkip_key(priv, idx, |
862 | ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, | 904 | ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, |
863 | (u8 *) &priv->tkip_key[idx], | 905 | priv->keys[idx].key, |
864 | tkip_iv, ORINOCO_SEQ_LEN, NULL, 0); | 906 | tkip_iv, ORINOCO_SEQ_LEN, NULL, 0); |
865 | if (err) | 907 | if (err) |
866 | printk(KERN_ERR "%s: Error %d setting TKIP key" | 908 | printk(KERN_ERR "%s: Error %d setting TKIP key" |
@@ -918,16 +960,14 @@ static int orinoco_ioctl_get_encodeext(struct net_device *dev, | |||
918 | break; | 960 | break; |
919 | case ORINOCO_ALG_WEP: | 961 | case ORINOCO_ALG_WEP: |
920 | ext->alg = IW_ENCODE_ALG_WEP; | 962 | ext->alg = IW_ENCODE_ALG_WEP; |
921 | ext->key_len = min_t(u16, le16_to_cpu(priv->keys[idx].len), | 963 | ext->key_len = min(priv->keys[idx].key_len, max_key_len); |
922 | max_key_len); | 964 | memcpy(ext->key, priv->keys[idx].key, ext->key_len); |
923 | memcpy(ext->key, priv->keys[idx].data, ext->key_len); | ||
924 | encoding->flags |= IW_ENCODE_ENABLED; | 965 | encoding->flags |= IW_ENCODE_ENABLED; |
925 | break; | 966 | break; |
926 | case ORINOCO_ALG_TKIP: | 967 | case ORINOCO_ALG_TKIP: |
927 | ext->alg = IW_ENCODE_ALG_TKIP; | 968 | ext->alg = IW_ENCODE_ALG_TKIP; |
928 | ext->key_len = min_t(u16, sizeof(struct orinoco_tkip_key), | 969 | ext->key_len = min(priv->keys[idx].key_len, max_key_len); |
929 | max_key_len); | 970 | memcpy(ext->key, priv->keys[idx].key, ext->key_len); |
930 | memcpy(ext->key, &priv->tkip_key[idx], ext->key_len); | ||
931 | encoding->flags |= IW_ENCODE_ENABLED; | 971 | encoding->flags |= IW_ENCODE_ENABLED; |
932 | break; | 972 | break; |
933 | } | 973 | } |