diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/ath5k/pcu.c | 58 |
1 files changed, 34 insertions, 24 deletions
diff --git a/drivers/net/wireless/ath5k/pcu.c b/drivers/net/wireless/ath5k/pcu.c index 79879f2d426c..ad7ea36502bd 100644 --- a/drivers/net/wireless/ath5k/pcu.c +++ b/drivers/net/wireless/ath5k/pcu.c | |||
@@ -1013,6 +1013,23 @@ int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry) | |||
1013 | AR5K_KEYTABLE_VALID; | 1013 | AR5K_KEYTABLE_VALID; |
1014 | } | 1014 | } |
1015 | 1015 | ||
1016 | static | ||
1017 | int ath5k_keycache_type(const struct ieee80211_key_conf *key) | ||
1018 | { | ||
1019 | switch (key->alg) { | ||
1020 | case ALG_TKIP: | ||
1021 | return AR5K_KEYTABLE_TYPE_TKIP; | ||
1022 | case ALG_CCMP: | ||
1023 | return AR5K_KEYTABLE_TYPE_CCM; | ||
1024 | case ALG_WEP: | ||
1025 | if (key->keylen == LEN_WEP40) | ||
1026 | return AR5K_KEYTABLE_TYPE_40; | ||
1027 | else if (key->keylen == LEN_WEP104) | ||
1028 | return AR5K_KEYTABLE_TYPE_104; | ||
1029 | } | ||
1030 | return -EINVAL; | ||
1031 | } | ||
1032 | |||
1016 | /* | 1033 | /* |
1017 | * Set a key entry on the table | 1034 | * Set a key entry on the table |
1018 | */ | 1035 | */ |
@@ -1027,6 +1044,7 @@ int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, | |||
1027 | u32 keytype; | 1044 | u32 keytype; |
1028 | u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; | 1045 | u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; |
1029 | bool is_tkip; | 1046 | bool is_tkip; |
1047 | const u8 *key_ptr; | ||
1030 | 1048 | ||
1031 | ATH5K_TRACE(ah->ah_sc); | 1049 | ATH5K_TRACE(ah->ah_sc); |
1032 | 1050 | ||
@@ -1042,33 +1060,25 @@ int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, | |||
1042 | (is_tkip && micentry > AR5K_KEYTABLE_SIZE)) | 1060 | (is_tkip && micentry > AR5K_KEYTABLE_SIZE)) |
1043 | return -EOPNOTSUPP; | 1061 | return -EOPNOTSUPP; |
1044 | 1062 | ||
1045 | switch (keylen) { | 1063 | if (unlikely(keylen > 16)) |
1046 | /* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit */ | 1064 | return -EOPNOTSUPP; |
1047 | case 40 / 8: | ||
1048 | memcpy(&key_v[0], key->key, 5); | ||
1049 | keytype = AR5K_KEYTABLE_TYPE_40; | ||
1050 | break; | ||
1051 | 1065 | ||
1052 | /* WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit */ | 1066 | keytype = ath5k_keycache_type(key); |
1053 | case 104 / 8: | 1067 | if (keytype < 0) |
1054 | memcpy(&key_v[0], &key->key[0], 6); | 1068 | return keytype; |
1055 | memcpy(&key_v[2], &key->key[6], 6); | ||
1056 | memcpy(&key_v[4], &key->key[12], 1); | ||
1057 | keytype = AR5K_KEYTABLE_TYPE_104; | ||
1058 | break; | ||
1059 | /* WEP/TKIP 128-bit = 128-bit entered key + 24 bit IV = 152-bit */ | ||
1060 | case 128 / 8: | ||
1061 | memcpy(&key_v[0], &key->key[0], 6); | ||
1062 | memcpy(&key_v[2], &key->key[6], 6); | ||
1063 | memcpy(&key_v[4], &key->key[12], 4); | ||
1064 | keytype = is_tkip ? | ||
1065 | AR5K_KEYTABLE_TYPE_TKIP : | ||
1066 | AR5K_KEYTABLE_TYPE_128; | ||
1067 | break; | ||
1068 | 1069 | ||
1069 | default: | 1070 | /* |
1070 | return -EINVAL; /* shouldn't happen */ | 1071 | * each key block is 6 bytes wide, written as pairs of |
1072 | * alternating 32 and 16 bit le values. | ||
1073 | */ | ||
1074 | key_ptr = key->key; | ||
1075 | for (i = 0; keylen >= 6; keylen -= 6) { | ||
1076 | memcpy(&key_v[i], key_ptr, 6); | ||
1077 | i += 2; | ||
1078 | key_ptr += 6; | ||
1071 | } | 1079 | } |
1080 | if (keylen) | ||
1081 | memcpy(&key_v[i], key_ptr, keylen); | ||
1072 | 1082 | ||
1073 | /* intentionally corrupt key until mic is installed */ | 1083 | /* intentionally corrupt key until mic is installed */ |
1074 | if (is_tkip) { | 1084 | if (is_tkip) { |