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