1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. 4 * All rights reserved. 5 * 6 * Purpose: Implement functions for 802.11i Key management 7 * 8 * Author: Jerry Chen 9 * 10 * Date: May 29, 2003 11 * 12 */ 13 14 #include "tmacro.h" 15 #include "key.h" 16 #include "mac.h" 17 18 static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr, 19 struct ieee80211_key_conf *key, u32 key_type, 20 u32 mode, bool onfly_latch) 21 { 22 struct vnt_private *priv = hw->priv; 23 u8 broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 24 u16 key_mode = 0; 25 u32 entry = 0; 26 u8 *bssid; 27 u8 key_inx = key->keyidx; 28 u8 i; 29 30 if (mac_addr) 31 bssid = mac_addr; 32 else 33 bssid = &broadcast[0]; 34 35 if (key_type != VNT_KEY_DEFAULTKEY) { 36 for (i = 0; i < (MAX_KEY_TABLE - 1); i++) { 37 if (!test_bit(i, &priv->key_entry_inuse)) { 38 set_bit(i, &priv->key_entry_inuse); 39 40 key->hw_key_idx = i; 41 entry = key->hw_key_idx; 42 break; 43 } 44 } 45 } 46 47 switch (key_type) { 48 case VNT_KEY_DEFAULTKEY: 49 /* default key last entry */ 50 entry = MAX_KEY_TABLE - 1; 51 key->hw_key_idx = entry; 52 fallthrough; 53 case VNT_KEY_ALLGROUP: 54 key_mode |= VNT_KEY_ALLGROUP; 55 if (onfly_latch) 56 key_mode |= VNT_KEY_ONFLY_ALL; 57 fallthrough; 58 case VNT_KEY_GROUP_ADDRESS: 59 key_mode |= mode; 60 fallthrough; 61 case VNT_KEY_GROUP: 62 key_mode |= (mode << 4); 63 key_mode |= VNT_KEY_GROUP; 64 break; 65 case VNT_KEY_PAIRWISE: 66 key_mode |= mode; 67 key_inx = 4; 68 break; 69 default: 70 return -EINVAL; 71 } 72 73 if (onfly_latch) 74 key_mode |= VNT_KEY_ONFLY; 75 76 if (mode == KEY_CTL_WEP) { 77 if (key->keylen == WLAN_KEY_LEN_WEP40) 78 key->key[15] &= 0x7f; 79 if (key->keylen == WLAN_KEY_LEN_WEP104) 80 key->key[15] |= 0x80; 81 } 82 83 MACvSetKeyEntry(priv, key_mode, entry, key_inx, 84 bssid, (u32 *)key->key, priv->local_id); 85 86 return 0; 87 } 88 89 int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta, 90 struct ieee80211_vif *vif, struct ieee80211_key_conf *key) 91 { 92 struct ieee80211_bss_conf *conf = &vif->bss_conf; 93 struct vnt_private *priv = hw->priv; 94 u8 *mac_addr = NULL; 95 u8 key_dec_mode = 0; 96 int ret = 0; 97 u32 u; 98 99 if (sta) 100 mac_addr = &sta->addr[0]; 101 102 switch (key->cipher) { 103 case 0: 104 for (u = 0 ; u < MAX_KEY_TABLE; u++) 105 MACvDisableKeyEntry(priv, u); 106 return ret; 107 108 case WLAN_CIPHER_SUITE_WEP40: 109 case WLAN_CIPHER_SUITE_WEP104: 110 for (u = 0; u < MAX_KEY_TABLE; u++) 111 MACvDisableKeyEntry(priv, u); 112 113 vnt_set_keymode(hw, mac_addr, 114 key, VNT_KEY_DEFAULTKEY, KEY_CTL_WEP, true); 115 116 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; 117 118 return ret; 119 case WLAN_CIPHER_SUITE_TKIP: 120 key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; 121 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; 122 123 key_dec_mode = KEY_CTL_TKIP; 124 125 break; 126 case WLAN_CIPHER_SUITE_CCMP: 127 key_dec_mode = KEY_CTL_CCMP; 128 129 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; 130 } 131 132 if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { 133 vnt_set_keymode(hw, mac_addr, 134 key, VNT_KEY_PAIRWISE, key_dec_mode, true); 135 } else { 136 vnt_set_keymode(hw, mac_addr, 137 key, VNT_KEY_DEFAULTKEY, key_dec_mode, true); 138 139 vnt_set_keymode(hw, (u8 *)conf->bssid, 140 key, VNT_KEY_GROUP_ADDRESS, key_dec_mode, true); 141 } 142 143 return 0; 144 } 145