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