xref: /openbmc/linux/drivers/staging/vt6655/key.c (revision f21e49be)
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