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