key.c (3120B)
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 "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 else 32 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}