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