blob: 3db575e4fa0bac0fe52e7cb0a376ab195f11f055 [file] [log] [blame]
developer8fb759f2022-02-21 16:39:38 +08001/* Copyright (C) 2021 Mediatek Inc. */
2#define _GNU_SOURCE
3
4#include "mtk_vendor_nl80211.h"
5#include "mt76-vendor.h"
6#include "mwctl.h"
7
8DECLARE_SECTION(set);
9
10#define AP_SECURITY_OPTIONS "[authmode=[open|shared|wepauto|wpa|wpapsk|wpanone|wpa2|wpa2mix|wpa2psk|wpa3|" \
11 "wpa3-192|wpa3psk|wpa2pskwpa3psk|wpa2pskmixwpa3psk|wpa1wpa2|wpapskwpa2psk|wpa_aes_wpa2_tkipaes|wpa" \
12 "_aes_wpa2_tkip|wpa_tkip_wpa2_aes|wpa_tkip_wpa2_tkipaes|wpa_tkipaes_wpa2_aes|wpa_tkipaes_wpa2_tkip" \
13 "aes|wpa_tkipaes_wpa2_tkip|owe|files_sha256|files_sha384|waicert|waipsk|dpp|dppwpa2psk|dppwap3psk|" \
14 "dppwpa3pskwpa2psk|wpa2-ent-osen]] [encryptype=[none|wep|tkip|aes|ccmp128|ccmp256|gcmp128|gcmp25" \
15 "6|tkipaes|tkipcmp128|wpa_aes_wpa2_tkipaes|wpa_aes_wpa2_tkip|wpa_tkip_wpa2_aes|wpa_tkip_wpa2_tkipa" \
16 "es|wpa_tkipaes_wpa2_aes|wpa_tkipaes_wpa2_tkipaes|wpa_tkipaes_wpa2_tkip|sms4]]" \
17 " [rekeyinterval=<seconds>] [rekeymethod=[time|pkt]] [defaultkeyid=<pairwise key id>]" \
18 "[wep_key1=<key>] [wep_key2=<key>] [wep_key3=<key>] [wep_key4=<key>] [passphrase=<passphrase>]" \
19 " [pmf_capable=<0 or 1>] [pmf_require=<0 or 1>] [pmf_sha256=<0 or 1>]"
20
21#define MAX_SEURITY_PARAM_LEN 128
22
23struct security_option {
24 char option_name[MAX_SEURITY_PARAM_LEN];
25 int (* attr_put)(struct nl_msg *msg, char *value);
26};
27
28int auth_attr_put(struct nl_msg *msg, char *value);
29int encryptype_attr_put(struct nl_msg *msg, char *value);
30
31int rekeyinterval_attr_put(struct nl_msg *msg, char *value)
32{
33 unsigned long interval;
34
35 interval = strtoul(value, NULL, 10);
36
37 if (interval < 10 || interval >= 0x3ffffff)
38 return -EINVAL;
39
40 if (nla_put_u32(msg, MTK_NL80211_VENDOR_ATTR_AP_SECURITY_REKEYINTERVAL, interval))
41 return -EMSGSIZE;
42
43 return 0;
44}
45
46int rekeymethod_attr_put(struct nl_msg *msg, char *value)
47{
48 unsigned char method;
49
50 if (strlen(value) == strlen("time") && !strncmp(value, "time", strlen("time")))
51 method = 0;
52 else if (strlen(value) == strlen("pkt") && !strncmp(value, "pkt", strlen("pkt")))
53 method = 1;
54 else
55 return -EINVAL;
56
57 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_AP_SECURITY_REKEYMETHOD, method))
58 return -EMSGSIZE;
59
60 return 0;
61}
62
63int defaultkeyid_attr_put(struct nl_msg *msg, char *value)
64{
65 unsigned long key_id;
66
67 key_id = strtoul(value, NULL, 10);
68
69 if (key_id < 1 || key_id > 4 )
70 return -EINVAL;
71
72 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_AP_SECURITY_DEFAULTKEYID, key_id))
73 return -EMSGSIZE;
74
75 return 0;
76}
77
78#define isxdigit(_char) \
79 (('0' <= (_char) && (_char) <= '9') ||\
80 ('a' <= (_char) && (_char) <= 'f') || \
81 ('A' <= (_char) && (_char) <= 'F') \
82 )
83
84int wep_key_attr_put(struct nl_msg *msg, char *value, unsigned char key_idx)
85{
86 struct wep_key_param k;
87 int len, i;
88 char k_v[2];
89 unsigned long tmp_key;
90
91 memset(&k, 0, sizeof(k));
92
93 k.key_idx = key_idx;
94 len = strlen(value);
95
96 switch (len) {
97 case 5: /*wep 40 Ascii type*/
98 case 13: /*wep 104 Ascii type*/
99 case 16: /*wep 128 Ascii type*/
100 k.key_len = len;
101 memcpy(k.key, value, len);
102 break;
103 case 10: /*wep 40 Hex type*/
104 case 26: /*wep 104 Hex type*/
105 case 32: /*wep 128 Hex type*/
106 for (i = 0; i < len; i++) {
107 if (!isxdigit(*(value + i)))
108 return -EINVAL; /*Not Hex value;*/
109 }
110 k.key_len = len / 2;
111 for (i = 0; i < (len / 2); i++) {
112 memcpy(k_v, value + i * 2, 2);
113 tmp_key = strtoul(k_v, NULL, 10);
114 k.key[i] = (unsigned char)tmp_key;
115 }
116 k.key[k.key_len] = '\0';
117 break;
118 default:
119 return -EINVAL;
120 }
121
122 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_AP_SECURITY_WEPKEY, sizeof(k), &k))
123 return -EMSGSIZE;
124
125 return 0;
126}
127
128int wep_key1_attr_put(struct nl_msg *msg, char *value)
129{
130 return wep_key_attr_put(msg, value, 0);
131}
132
133int wep_key2_attr_put(struct nl_msg *msg, char *value)
134{
135 return wep_key_attr_put(msg, value, 1);
136}
137
138int wep_key3_attr_put(struct nl_msg *msg, char *value)
139{
140 return wep_key_attr_put(msg, value, 2);
141}
142
143int wep_key4_attr_put(struct nl_msg *msg, char *value)
144{
145 return wep_key_attr_put(msg, value, 3);
146}
147
148int passphrase_attr_put(struct nl_msg *msg, char *value)
149{
150 int len;
151
152 len = strlen(value);
153
154 if (len >= 65)
155 return -EINVAL;
156
157 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_AP_SECURITY_PASSPHRASE, len, value))
158 return -EMSGSIZE;
159
160 return 0;
161}
162
163int pmf_capable_attr_put(struct nl_msg *msg, char *value)
164{
165 unsigned char pmf_capable;
166
167 if (!value)
168 return -EINVAL;
169
170 if (*value == '0')
171 pmf_capable = 0;
172 else if (*value == '1')
173 pmf_capable = 1;
174 else
175 return -EINVAL;
176
177 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_AP_SECURITY_PMF_CAPABLE, pmf_capable))
178 return -EMSGSIZE;
179
180 return 0;
181}
182
183int pmf_require_attr_put(struct nl_msg *msg, char *value)
184{
185 unsigned char pmf_require;
186
187 if (!value)
188 return -EINVAL;
189
190 if (*value == '0')
191 pmf_require = 0;
192 else if (*value == '1')
193 pmf_require = 1;
194 else
195 return -EINVAL;
196
197 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_AP_SECURITY_PMF_REQUIRE, pmf_require))
198 return -EMSGSIZE;
199
200 return 0;
201}
202
203int pmf_sha256_attr_put(struct nl_msg *msg, char *value)
204{
205 unsigned char pmf_sha256;
206
207 if (!value)
208 return -EINVAL;
209
210 if (*value == '0')
211 pmf_sha256 = 0;
212 else if (*value == '1')
213 pmf_sha256 = 1;
214 else
215 return -EINVAL;
216
217 if (nla_put_u8(msg, MTK_NL80211_VENDOR_ATTR_AP_SECURITY_PMF_SHA256, pmf_sha256))
218 return -EMSGSIZE;
219
220 return 0;
221}
222
223struct security_option sec_opt[] = {
224 {"authmode", auth_attr_put},
225 {"encryptype", encryptype_attr_put},
226 {"rekeyinterval", rekeyinterval_attr_put},
227 {"rekeymethod", rekeymethod_attr_put},
228 {"defaultkeyid", defaultkeyid_attr_put},
229 {"wep_key1", wep_key1_attr_put},
230 {"wep_key2", wep_key2_attr_put},
231 {"wep_key3", wep_key3_attr_put},
232 {"wep_key4", wep_key4_attr_put},
233 {"passphrase", passphrase_attr_put},
234 {"pmf_capable", pmf_capable_attr_put},
235 {"pmf_require", pmf_require_attr_put},
236 {"pmf_sha256", pmf_sha256_attr_put},
237};
238
239struct auth_mode_option {
240 char option_name[MAX_SEURITY_PARAM_LEN];
241 enum mtk_vendor_attr_authmode mode;
242};
243
244struct auth_mode_option auth_opt[] = {
245 {"open", NL80211_AUTH_OPEN},
246 {"shared", NL80211_AUTH_SHARED},
247 {"wepauto", NL80211_AUTH_WEPAUTO},
248 {"wpa", NL80211_AUTH_WPA},
249 {"wpapsk", NL80211_AUTH_WPAPSK},
250 {"wpanone", NL80211_AUTH_WPANONE},
251 {"wpa2", NL80211_AUTH_WPA2},
252 {"wpa2mix", NL80211_AUTH_WPA2MIX},
253 {"wpa2psk", NL80211_AUTH_WPA2PSK},
254 {"wpa3", NL80211_AUTH_WPA3},
255 {"wpa3-192", NL80211_AUTH_WPA3_192},
256 {"wpa3psk", NL80211_AUTH_WPA3PSK},
257 {"wpa2pskwpa3psk", NL80211_AUTH_WPA2PSKWPA3PSK},
258 {"wpa2pskmixwpa3psk", NL80211_AUTH_WPA2PSKMIXWPA3PSK},
259 {"wpa1wpa2", NL80211_AUTH_WPA1WPA2},
260 {"wpapskwpa2psk", NL80211_AUTH_WPAPSKWPA2PSK},
261 {"wpa_aes_wpa2_tkipaes", NL80211_AUTH_WPA_AES_WPA2_TKIPAES},
262 {"wpa_aes_wpa2_tkip", NL80211_AUTH_WPA_AES_WPA2_TKIP},
263 {"wpa_tkip_wpa2_aes", NL80211_AUTH_WPA_TKIP_WPA2_AES},
264 {"wpa_tkip_wpa2_tkipaes", NL80211_AUTH_WPA_TKIP_WPA2_TKIPAES},
265 {"wpa_tkipaes_wpa2_aes", NL80211_AUTH_WPA_TKIPAES_WPA2_AES},
266 {"wpa_tkipaes_wpa2_tkipaes", NL80211_AUTH_WPA_TKIPAES_WPA2_TKIPAES},
267 {"wpa_tkipaes_wpa2_tkip", NL80211_AUTH_WPA_TKIPAES_WPA2_TKIP},
268 {"owe", NL80211_AUTH_OWE},
269 {"files_sha256", NL80211_AUTH_FILS_SHA256},
270 {"files_sha384", NL80211_AUTH_FILS_SHA384},
271 {"waicert", NL80211_AUTH_WAICERT},
272 {"waipsk", NL80211_AUTH_WAIPSK},
273 {"dpp", NL80211_AUTH_DPP},
274 {"dppwpa2psk", NL80211_AUTH_DPPWPA2PSK},
275 {"dppwap3psk", NL80211_AUTH_DPPWPA3PSK},
276 {"dppwpa3pskwpa2psk", NL80211_AUTH_DPPWPA3PSKWPA2PSK},
277 {"wpa2-ent-osen", NL80211_AUTH_WPA2_ENT_OSEN},
278};
279
280int auth_attr_put(struct nl_msg *msg, char *value)
281{
282 int i;
283
284 for (i = 0; i < (sizeof(auth_opt)/sizeof(auth_opt[0])); i++) {
285 if (strlen(auth_opt[i].option_name) == strlen(value) &&
286 !strncmp(auth_opt[i].option_name, value, strlen(value))) {
287 if (nla_put_u32(msg, MTK_NL80211_VENDOR_ATTR_AP_SECURITY_AUTHMODE, auth_opt[i].mode))
288 return -EMSGSIZE;
289 }
290 }
291
292 return 0;
293}
294
295struct encryptype_option {
296 char option_name[MAX_SEURITY_PARAM_LEN];
297 enum mtk_vendor_attr_encryptype type;
298};
299
300struct encryptype_option encryp_opt[] = {
301 {"none", NL80211_ENCRYPTYPE_NONE},
302 {"wep", NL80211_ENCRYPTYPE_WEP},
303 {"tkip", NL80211_ENCRYPTYPE_TKIP},
304 {"aes", NL80211_ENCRYPTYPE_AES},
305 {"ccmp128", NL80211_ENCRYPTYPE_CCMP128},
306 {"ccmp256", NL80211_ENCRYPTYPE_CCMP256},
307 {"gcmp128|gcmp256", NL80211_ENCRYPTYPE_GCMP128},
308 {"tkipaes", NL80211_ENCRYPTYPE_GCMP256},
309 {"tkipcmp128", NL80211_ENCRYPTYPE_TKIPCCMP128},
310 {"wpa_aes_wpa2_tkipaes", NL80211_ENCRYPTYPE_WPA_AES_WPA2_TKIPAES},
311 {"wpa_aes_wpa2_tkip", NL80211_ENCRYPTYPE_WPA_AES_WPA2_TKIP},
312 {"wpa_tkip_wpa2_aes", NL80211_ENCRYPTYPE_WPA_TKIP_WPA2_AES},
313 {"wpa_tkip_wpa2_tkipaes", NL80211_ENCRYPTYPE_WPA_TKIP_WPA2_TKIPAES},
314 {"wpa_tkipaes_wpa2_aes", NL80211_ENCRYPTYPE_WPA_TKIPAES_WPA2_AES},
315 {"wpa_tkipaes_wpa2_tkipaes", NL80211_ENCRYPTYPE_WPA_TKIPAES_WPA2_TKIPAES},
316 {"wpa_tkipaes_wpa2_tkip", NL80211_ENCRYPTYPE_WPA_TKIPAES_WPA2_TKIP},
317 {"sms4", NL80211_ENCRYPTYPE_SMS4},
318};
319
320int encryptype_attr_put(struct nl_msg *msg, char *value)
321{
322 int i;
323
324 for (i = 0; i < (sizeof(encryp_opt)/sizeof(encryp_opt[0])); i++) {
325 if (strlen(encryp_opt[i].option_name) == strlen(value) &&
326 !strncmp(encryp_opt[i].option_name, value, strlen(value))) {
327 if (nla_put_u32(msg, MTK_NL80211_VENDOR_ATTR_AP_SECURITY_ENCRYPTYPE, encryp_opt[i].type))
328 return -EMSGSIZE;
329 }
330 }
331
332 return 0;
333}
334
335int handle_ap_security_set(struct nl_msg *msg, int argc,
336 char **argv, void *ctx)
337{
338 void *data;
339 char *ptr, *param_str, *val_str, invalide = 0;
340 int i, j;
341
342 if (!argc)
343 return -EINVAL;
344
345 data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
346 if (!data)
347 return -ENOMEM;
348
349 for (i = 0; i < argc; i++) {
350 ptr = argv[i];
351 param_str = ptr;
352 val_str = strchr(ptr, '=');
353
354 if (!val_str)
355 continue;
356
357 *val_str++ = 0;
358
359 for (j = 0; j < (sizeof(sec_opt) / sizeof(sec_opt[0])); j++) {
360 if (strlen(sec_opt[j].option_name) == strlen(param_str) &&
361 !strncmp(sec_opt[j].option_name, param_str, strlen(param_str)))
362 break;
363 }
364
365 if (j != (sizeof(sec_opt) / sizeof(sec_opt[0]))) {
366 if (sec_opt[j].attr_put(msg, val_str) < 0)
367 printf("invalide argument %s=%s, ignore it\n", param_str, val_str);
368 else
369 invalide = 1;
370 }
371 }
372
373 nla_nest_end(msg, data);
374
375 if (!invalide)
376 return -EINVAL;
377
378 return 0;
379}
380
381COMMAND(set, ap_security,
382 AP_SECURITY_OPTIONS,
383 MTK_NL80211_VENDOR_SUBCMD_SET_AP_SECURITY, 0, CIB_NETDEV, handle_ap_security_set,
384 "Set the security information to specific bss\n");