/* * Reset a key entry on the table */ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) { unsigned int i; ATH5K_TRACE(ah->ah_sc); AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); for (i = 0; i < AR5K_KEYCACHE_SIZE; i++) ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i)); /* * Set NULL encryption on AR5212+ * * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5) * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007 * * Note2: Windows driver (ndiswrapper) sets this to * 0x00000714 instead of 0x00000007 */ if (ah->ah_version > AR5K_AR5211) ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, AR5K_KEYTABLE_TYPE(entry)); return 0; }
/* * Reset a key entry on the table */ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) { unsigned int i, type; u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; ATH5K_TRACE(ah->ah_sc); AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry)); for (i = 0; i < AR5K_KEYCACHE_SIZE; i++) ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i)); /* Reset associated MIC entry if TKIP * is enabled located at offset (entry + 64) */ if (type == AR5K_KEYTABLE_TYPE_TKIP) { AR5K_ASSERT_ENTRY(micentry, AR5K_KEYTABLE_SIZE); for (i = 0; i < AR5K_KEYCACHE_SIZE / 2 ; i++) ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(micentry, i)); } /* * Set NULL encryption on AR5212+ * * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5) * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007 * * Note2: Windows driver (ndiswrapper) sets this to * 0x00000714 instead of 0x00000007 */ if (ah->ah_version >= AR5K_AR5211) { ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, AR5K_KEYTABLE_TYPE(entry)); if (type == AR5K_KEYTABLE_TYPE_TKIP) { ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, AR5K_KEYTABLE_TYPE(micentry)); } } return 0; }
/* * Set a key entry on the table */ int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, const struct ieee80211_key_conf *key, const u8 *mac) { unsigned int i; __le32 key_v[5] = {}; u32 keytype; ATH5K_TRACE(ah->ah_sc); /* key->keylen comes in from mac80211 in bytes */ if (key->keylen > AR5K_KEYTABLE_SIZE / 8) return -EOPNOTSUPP; switch (key->keylen) { /* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit */ case 40 / 8: memcpy(&key_v[0], key->key, 5); keytype = AR5K_KEYTABLE_TYPE_40; break; /* WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit */ case 104 / 8: memcpy(&key_v[0], &key->key[0], 6); memcpy(&key_v[2], &key->key[6], 6); memcpy(&key_v[4], &key->key[12], 1); keytype = AR5K_KEYTABLE_TYPE_104; break; /* WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit */ case 128 / 8: memcpy(&key_v[0], &key->key[0], 6); memcpy(&key_v[2], &key->key[6], 6); memcpy(&key_v[4], &key->key[12], 4); keytype = AR5K_KEYTABLE_TYPE_128; break; default: return -EINVAL; /* shouldn't happen */ } for (i = 0; i < ARRAY_SIZE(key_v); i++) ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]), AR5K_KEYTABLE_OFF(entry, i)); ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry)); return ath5k_hw_set_key_lladdr(ah, entry, mac); }
/* * Set a key entry on the table */ int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, const struct ieee80211_key_conf *key, const u8 *mac) { unsigned int i; int keylen; __le32 key_v[5] = {}; __le32 key0 = 0, key1 = 0; __le32 *rxmic, *txmic; int keytype; u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; bool is_tkip; const u8 *key_ptr; ATH5K_TRACE(ah->ah_sc); is_tkip = (key->alg == ALG_TKIP); /* * key->keylen comes in from mac80211 in bytes. * TKIP is 128 bit + 128 bit mic */ keylen = (is_tkip) ? (128 / 8) : key->keylen; if (entry > AR5K_KEYTABLE_SIZE || (is_tkip && micentry > AR5K_KEYTABLE_SIZE)) return -EOPNOTSUPP; if (unlikely(keylen > 16)) return -EOPNOTSUPP; keytype = ath5k_keycache_type(key); if (keytype < 0) return keytype; /* * each key block is 6 bytes wide, written as pairs of * alternating 32 and 16 bit le values. */ key_ptr = key->key; for (i = 0; keylen >= 6; keylen -= 6) { memcpy(&key_v[i], key_ptr, 6); i += 2; key_ptr += 6; } if (keylen) memcpy(&key_v[i], key_ptr, keylen); /* intentionally corrupt key until mic is installed */ if (is_tkip) { key0 = key_v[0] = ~key_v[0]; key1 = key_v[1] = ~key_v[1]; } for (i = 0; i < ARRAY_SIZE(key_v); i++) ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]), AR5K_KEYTABLE_OFF(entry, i)); ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry)); if (is_tkip) { /* Install rx/tx MIC */ rxmic = (__le32 *) &key->key[16]; txmic = (__le32 *) &key->key[24]; if (ah->ah_combined_mic) { key_v[0] = rxmic[0]; key_v[1] = cpu_to_le32(le32_to_cpu(txmic[0]) >> 16); key_v[2] = rxmic[1]; key_v[3] = cpu_to_le32(le32_to_cpu(txmic[0]) & 0xffff); key_v[4] = txmic[1]; } else {