• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 
17 #include <unistd.h>
18 #include <net/if.h>
19 #include <sys/ioctl.h>
20 #include <sys/socket.h>
21 #include <pthread.h>
22 
23 #include "securec.h"
24 #include "wifi_hdi_common.h"
25 
26 #ifndef UT_TEST
27 #include "wifi_log.h"
28 #else
29 #define static
30 #define LOGI(...)
31 #define LOGE(...)
32 #endif
33 
34 #undef LOG_TAG
35 #define LOG_TAG "WifiHdiCommon"
36 
hex2num(char c)37 static int hex2num(char c)
38 {
39     if (c >= '0' && c <= '9') {
40         return c - '0';
41     }
42     if (c >= 'a' && c <= 'f') {
43         return c - 'a' + HDI_POS_TEN;
44     }
45     if (c >= 'A' && c <= 'F') {
46         return c - 'A' + HDI_POS_TEN;
47     }
48     return -1;
49 }
50 
hex2byte(const char * hex)51 int hex2byte(const char *hex)
52 {
53     int a, b;
54     a = hex2num(*hex++);
55     if (a < 0) {
56         return -1;
57     }
58     b = hex2num(*hex++);
59     if (b < 0) {
60         return -1;
61     }
62     return (int)(((unsigned int)a << HDI_POS_FOURTH) | (unsigned int)b);
63 }
64 
DealDigital(u8 * buf,const char ** pos,size_t * len)65 static void DealDigital(u8 *buf, const char **pos, size_t *len)
66 {
67     int val;
68     switch (**pos) {
69         case '0':
70         case '1':
71         case '2':
72         case '3':
73         case '4':
74         case '5':
75         case '6':
76         case '7':
77             val = **pos++ - '0';
78             if (**pos >= '0' && **pos <= '7') {
79                 val = val * HDI_POS_EIGHT + (**pos++ - '0');
80             }
81             if (**pos >= '0' && **pos <= '7') {
82                 val = val * HDI_POS_EIGHT + (**pos++ - '0');
83             }
84             buf[(*len)++] = val;
85             return;
86         default:
87             return;
88     }
89 }
90 
DealSymbol(u8 * buf,const char ** pos,size_t * len)91 static void DealSymbol(u8 *buf, const char **pos, size_t *len)
92 {
93     int val;
94     switch (**pos) {
95         case '\\':
96             buf[(*len)++] = '\\';
97             (*pos)++;
98             return;
99         case '"':
100             buf[(*len)++] = '"';
101             (*pos)++;
102             return;
103         case 'n':
104             buf[(*len)++] = '\n';
105             (*pos)++;
106             return;
107         case 'r':
108             buf[(*len)++] = '\r';
109             (*pos)++;
110             return;
111         case 't':
112             buf[(*len)++] = '\t';
113             (*pos)++;
114             return;
115         case 'e':
116             buf[(*len)++] = '\033';
117             (*pos)++;
118             return;
119         case 'x':
120             (*pos)++;
121             val = hex2byte(*pos);
122             if (val < 0) {
123                 val = hex2num(**pos);
124                 if (val < 0) {
125                     return;
126                 }
127                 buf[(*len)++] = val;
128                 (*pos)++;
129             } else {
130                 buf[(*len)++] = val;
131                 (*pos) += HDI_POS_SECOND;
132             }
133             return;
134         default:
135             DealDigital(buf, pos, len);
136             return;
137     }
138 }
139 
PrintfDecode(u8 * buf,size_t maxlen,const char * str)140 size_t PrintfDecode(u8 *buf, size_t maxlen, const char *str)
141 {
142     const char *pos = str;
143     size_t len = 0;
144 
145     while (*pos) {
146         if (len + 1 >= maxlen) {
147             break;
148         }
149         switch (*pos) {
150             case '\\':
151                 pos++;
152                 DealSymbol(buf, &pos, &len);
153                 break;
154             default:
155                 buf[len++] = *pos++;
156                 break;
157         }
158     }
159     if (maxlen > len) {
160         buf[len] = '\0';
161     }
162     return len;
163 }
164 
HdiTxtPrintf(char * str,size_t size,const char * format,...)165 int HdiTxtPrintf(char *str, size_t size, const char *format, ...)
166 {
167     va_list ap;
168     int ret;
169 
170     va_start(ap, format);
171     ret = vsnprintf_s(str, size, size - 1, format, ap);
172     va_end(ap);
173     if (size > 0) {
174         str[size - 1] = '\0';
175     }
176     return ret;
177 }
178 
HdiGetCipherInfo(char * start,char * end,int ciphers,const char * delim)179 int HdiGetCipherInfo(char *start, char *end, int ciphers, const char *delim)
180 {
181     char *pos = start;
182     int ret;
183 
184     if ((unsigned int)ciphers & HDI_CIPHER_CCMP_256) {
185         HDI_HANDLE_CIPHER_INFO(ret, start, end, delim, "%sCCMP-256");
186     }
187     if ((unsigned int)ciphers & HDI_CIPHER_GCMP_256) {
188         HDI_HANDLE_CIPHER_INFO(ret, start, end, delim, "%sGCMP-256");
189     }
190     if ((unsigned int)ciphers & HDI_CIPHER_CCMP) {
191         HDI_HANDLE_CIPHER_INFO(ret, start, end, delim, "%sCCMP");
192     }
193     if ((unsigned int)ciphers & HDI_CIPHER_GCMP) {
194         HDI_HANDLE_CIPHER_INFO(ret, start, end, delim, "%sGCMP");
195     }
196     if ((unsigned int)ciphers & HDI_CIPHER_TKIP) {
197         HDI_HANDLE_CIPHER_INFO(ret, start, end, delim, "%sTKIP");
198     }
199     if ((unsigned int)ciphers & HDI_CIPHER_AES_128_CMAC) {
200         HDI_HANDLE_CIPHER_INFO(ret, start, end, delim, "%sAES-128-CMAC");
201     }
202     if ((unsigned int)ciphers & HDI_CIPHER_BIP_GMAC_128) {
203         HDI_HANDLE_CIPHER_INFO(ret, start, end, delim, "%sBIP-GMAC-128");
204     }
205     if ((unsigned int)ciphers & HDI_CIPHER_BIP_GMAC_256) {
206         HDI_HANDLE_CIPHER_INFO(ret, start, end, delim, "%sBIP-GMAC-256");
207     }
208     if ((unsigned int)ciphers & HDI_CIPHER_BIP_CMAC_256) {
209         HDI_HANDLE_CIPHER_INFO(ret, start, end, delim, "%sBIP-CMAC-256");
210     }
211     if ((unsigned int)ciphers & HDI_CIPHER_NONE) {
212         HDI_HANDLE_CIPHER_INFO(ret, start, end, delim, "%sNONE");
213     }
214 
215     return pos - start;
216 }
217 
HdiGetCipherTxt(char * pos,char * end,int cipher)218 static char* HdiGetCipherTxt(char *pos, char *end, int cipher)
219 {
220     int ret;
221     ret = HdiTxtPrintf(pos, end - pos, "-");
222     if (HdiCheckError(end - pos, ret)) {
223         return pos;
224     }
225     pos += ret;
226     ret = HdiGetCipherInfo(pos, end, cipher, "+");
227     if (ret < 0) {
228         return pos;
229     }
230     pos += ret;
231     return pos;
232 }
233 
HdiRsnIdToCipher(const uint8_t * s)234 static int HdiRsnIdToCipher(const uint8_t *s)
235 {
236     if (HDI_GET_RSN_ID(s) == HDI_CIPHER_SUITE_NONE) {
237         return HDI_CIPHER_NONE;
238     }
239     if (HDI_GET_RSN_ID(s) == HDI_CIPHER_SUITE_TKIP) {
240         return HDI_CIPHER_TKIP;
241     }
242     if (HDI_GET_RSN_ID(s) == HDI_CIPHER_SUITE_CCMP) {
243         return HDI_CIPHER_CCMP;
244     }
245     return 0;
246 }
247 
HdiRsnIdToCipherSuite(const uint8_t * s)248 static int HdiRsnIdToCipherSuite(const uint8_t *s)
249 {
250     if (HDI_GET_RSN_ID(s) == HDI_RSN_CIPHER_SUITE_NONE) {
251         return HDI_CIPHER_NONE;
252     }
253     if (HDI_GET_RSN_ID(s) == HDI_RSN_CIPHER_SUITE_TKIP) {
254         return HDI_CIPHER_TKIP;
255     }
256     if (HDI_GET_RSN_ID(s) == HDI_RSN_CIPHER_SUITE_CCMP) {
257         return HDI_CIPHER_CCMP;
258     }
259     if (HDI_GET_RSN_ID(s) == HDI_RSN_CIPHER_SUITE_GCMP) {
260         return HDI_CIPHER_GCMP;
261     }
262     if (HDI_GET_RSN_ID(s) == HDI_RSN_CIPHER_SUITE_CCMP_256) {
263         return HDI_CIPHER_CCMP_256;
264     }
265     if (HDI_GET_RSN_ID(s) == HDI_RSN_CIPHER_SUITE_GCMP_256) {
266         return HDI_CIPHER_GCMP_256;
267     }
268     if (HDI_GET_RSN_ID(s) == HDI_RSN_CIPHER_SUITE_BIP_GMAC_128) {
269         return HDI_CIPHER_BIP_GMAC_128;
270     }
271     if (HDI_GET_RSN_ID(s) == HDI_RSN_CIPHER_SUITE_BIP_GMAC_256) {
272         return HDI_CIPHER_BIP_GMAC_256;
273     }
274     if (HDI_GET_RSN_ID(s) == HDI_RSN_CIPHER_SUITE_BIP_CMAC_256) {
275         return HDI_CIPHER_BIP_CMAC_256;
276     }
277     if (HDI_GET_RSN_ID(s) == HDI_RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED) {
278         return HDI_CIPHER_GTK_NOT_USED;
279     }
280     return 0;
281 }
282 
HdiKeyMgmtToAuthMgmt(const uint8_t * s)283 static int HdiKeyMgmtToAuthMgmt(const uint8_t *s)
284 {
285     if (HDI_GET_RSN_ID(s) == HDI_AUTH_KEY_MGMT_UNSPEC) {
286         return HDI_KEY_MGMT;
287     }
288     if (HDI_GET_RSN_ID(s) == HDI_AUTH_KEY_MGMT_PSK_OVER) {
289         return HDI_KEY_MGMT_PSK;
290     }
291     if (HDI_GET_RSN_ID(s) == HDI_AUTH_KEY_MGMT_NONE) {
292         return HDI_KEY_MGMT_HDI_NONE;
293     }
294     return 0;
295 }
296 
HdiRsnKeyMgmtToAuthMgmt(const uint8_t * s)297 static int HdiRsnKeyMgmtToAuthMgmt(const uint8_t *s)
298 {
299     if (HDI_GET_RSN_ID(s) == HDI_RSN_AUTH_KEY_MGMT_UNSPEC) {
300         return HDI_KEY_MGMT;
301     }
302     if (HDI_GET_RSN_ID(s) == HDI_RSN_AUTH_KEY_MGMT_SAE) {
303         return HDI_KEY_MGMT_SAE;
304     }
305     if (HDI_GET_RSN_ID(s) == HDI_RSN_AUTH_KEY_MGMT_PSK_OVER) {
306         return HDI_KEY_MGMT_PSK;
307     }
308     if (HDI_GET_RSN_ID(s) == HDI_RSN_AUTH_KEY_MGMT_SUITE_B) {
309         return HDI_KEY_MGMT_SUITE_B;
310     }
311     if (HDI_GET_RSN_ID(s) == HDI_RSN_AUTH_KEY_MGMT_SUITE_B_192) {
312         return HDI_KEY_MGMT_SUITE_B_192;
313     }
314     if (HDI_GET_RSN_ID(s) == HDI_RSN_AUTH_KEY_MGMT_FILS_SHA256) {
315         return HDI_KEY_MGMT_FILS_SHA256;
316     }
317     if (HDI_GET_RSN_ID(s) == HDI_RSN_AUTH_KEY_MGMT_FILS_SHA384) {
318         return HDI_KEY_MGMT_FILS_SHA384;
319     }
320     if (HDI_GET_RSN_ID(s) == HDI_RSN_AUTH_KEY_MGMT_FT_FILS_SHA256) {
321         return HDI_KEY_MGMT_FT_FILS_SHA256;
322     }
323     if (HDI_GET_RSN_ID(s) == HDI_RSN_AUTH_KEY_MGMT_FT_FILS_SHA384) {
324         return HDI_KEY_MGMT_FT_FILS_SHA384;
325     }
326     if (HDI_GET_RSN_ID(s) == HDI_RSN_AUTH_KEY_MGMT_OSEN) {
327         return HDI_KEY_MGMT_OSEN;
328     }
329     if (HDI_GET_RSN_ID(s) == HDI_RSN_AUTH_KEY_MGMT_OWE) {
330         return HDI_KEY_MGMT_OWE;
331     }
332     if (HDI_GET_RSN_ID(s) == HDI_RSN_AUTH_KEY_MGMT_PSK_SHA256) {
333         return HDI_KEY_MGMT_PSK_SHA256;
334     }
335     if (HDI_GET_RSN_ID(s) == HDI_RSN_AUTH_KEY_MGMT_FT) {
336         return HDI_KEY_MGMT_FT_IEEE8021X;
337     }
338     if (HDI_GET_RSN_ID(s) == HDI_RSN_AUTH_KEY_MGMT_FT_PSK) {
339         return HDI_KEY_MGMT_FT_PSK;
340     }
341     if (HDI_GET_RSN_ID(s) == HDI_RSN_AUTH_KEY_MGMT_FT_SAE) {
342         return HDI_KEY_MGMT_FT_SAE;
343     }
344     if (HDI_GET_RSN_ID(s) == HDI_RSN_AUTH_KEY_MGMT_SHA256) {
345         return HDI_KEY_MGMT_IEEE8021X_SHA256;
346     }
347     return 0;
348 }
349 
HdiGetIe(const uint8_t * ies,size_t len,uint8_t eid)350 const uint8_t* HdiGetIe(const uint8_t *ies, size_t len, uint8_t eid)
351 {
352     const struct HdiElem *elem;
353 
354     if (!ies) {
355         return NULL;
356     }
357 
358     HDI_CHECK_ELEMENT_BY_ID(elem, eid, ies, len)
359         return &elem->id;
360 
361     return NULL;
362 }
363 
HdiBssGetIe(const uint8_t * ies,size_t len,uint8_t ie)364 const uint8_t* HdiBssGetIe(const uint8_t *ies, size_t len, uint8_t ie)
365 {
366     return HdiGetIe(ies, len, ie);
367 }
368 
HdiBssGetVendorIe(const uint8_t * ies,size_t len,uint32_t vendorType)369 const uint8_t *HdiBssGetVendorIe(const uint8_t *ies, size_t len, uint32_t vendorType)
370 {
371     const struct HdiElem *elem;
372     HDI_CHECK_ELEMENT_BY_ID(elem, HDI_EID_VENDOR_SPECIFIC, ies, len) {
373         if (elem->datalen >= HDI_POS_FOURTH && vendorType == HdiGetBe32(elem->data)) {
374             return &elem->id;
375         }
376     }
377 
378     return NULL;
379 }
380 
HdiBssGetVendorBeacon(const uint8_t * ies,size_t len,size_t beaconIeLen,uint32_t vendorType)381 const uint8_t* HdiBssGetVendorBeacon(const uint8_t *ies, size_t len, size_t beaconIeLen, uint32_t vendorType)
382 {
383     const struct HdiElem *elem;
384 
385     if (beaconIeLen == 0) {
386         return NULL;
387     }
388 
389     ies += len;
390 
391     HDI_CHECK_ELEMENT_BY_ID(elem, HDI_EID_VENDOR_SPECIFIC, ies, beaconIeLen) {
392         if (elem->datalen >= HDI_POS_FOURTH && vendorType == HdiGetBe32(elem->data)) {
393             return &elem->id;
394         }
395     }
396 
397     return NULL;
398 }
399 
HdiCheckValidWise(int cipher)400 int HdiCheckValidWise(int cipher)
401 {
402     return cipher == HDI_CIPHER_CCMP_256 ||
403         cipher == HDI_CIPHER_GCMP_256 ||
404         cipher == HDI_CIPHER_CCMP ||
405         cipher == HDI_CIPHER_GCMP ||
406         cipher == HDI_CIPHER_TKIP;
407 }
408 
HdiCheckValidGroup(int cipher)409 int HdiCheckValidGroup(int cipher)
410 {
411     return HdiCheckValidWise(cipher) ||
412         cipher == HDI_CIPHER_GTK_NOT_USED;
413 }
414 
HdiConvertIe(const uint8_t * hdiIe,size_t wpaIeLen,struct HdiIeData * data)415 int HdiConvertIe(const uint8_t *hdiIe, size_t wpaIeLen,
416              struct HdiIeData *data)
417 {
418     const struct HdiIeHdr *hdr;
419     const uint8_t *pos;
420     int left;
421     int i, count;
422 
423     if (memset_s(data, sizeof(*data), 0, sizeof(*data)) != EOK) {
424         LOGE("HdiConvertIe memset_s is failed");
425         return -1;
426     }
427     data->proto = HDI_PROTO_DEFAULT;
428     data->pairwiseCipher = HDI_CIPHER_TKIP;
429     data->groupCipher = HDI_CIPHER_TKIP;
430     data->keyMgmt = HDI_KEY_MGMT;
431     data->capabilities = 0;
432     data->pmkid = NULL;
433     data->numPmkid = 0;
434     data->mgmtGroupCipher = 0;
435 
436     if (wpaIeLen < sizeof(struct HdiIeHdr)) {
437         LOGI("ie len too short %{public}lu", (unsigned long) wpaIeLen);
438         return -1;
439     }
440 
441     hdr = (const struct HdiIeHdr *) hdiIe;
442 
443     if (hdr->elemId != HDI_EID_VENDOR_SPECIFIC ||
444         hdr->len != wpaIeLen - HDI_POS_SECOND ||
445         HDI_GET_RSN_ID(hdr->oui) != HDI_OUI_TYPE ||
446         HdiGetBe16(hdr->version) != HDI_VERSION) {
447         LOGI("malformed ie or unknown version");
448         return -1;
449     }
450 
451     pos = (const uint8_t *) (hdr + 1);
452     left = (int)(wpaIeLen - sizeof(*hdr));
453 
454     if (left >= HDI_SELECTOR_LEN) {
455         data->groupCipher = HdiRsnIdToCipher(pos);
456         pos += HDI_SELECTOR_LEN;
457         left -= HDI_SELECTOR_LEN;
458     } else if (left > 0) {
459         LOGI("ie length mismatch, %{public}u too much", left);
460         return -1;
461     }
462 
463     if (left >= HDI_POS_SECOND) {
464         data->pairwiseCipher = 0;
465         count = HdiGetBe16(pos);
466         pos += HDI_POS_SECOND;
467         left -= HDI_POS_SECOND;
468         if (count == 0 || count > left / HDI_SELECTOR_LEN) {
469             LOGI("ie count botch (pairwise), count %{public}u left %{public}u", count, left);
470             return -1;
471         }
472         for (i = 0; i < count; i++) {
473             data->pairwiseCipher = (int)((unsigned int)(data->pairwiseCipher) | (unsigned int)HdiRsnIdToCipher(pos));
474             pos += HDI_SELECTOR_LEN;
475             left -= HDI_SELECTOR_LEN;
476         }
477     } else if (left == 1) {
478         LOGI("ie too short (for key mgmt)");
479         return -1;
480     }
481 
482     if (left >= HDI_POS_SECOND) {
483         data->keyMgmt = 0;
484         count = HdiGetBe16(pos);
485         pos += HDI_POS_SECOND;
486         left -= HDI_POS_SECOND;
487         if (count == 0 || count > left / HDI_SELECTOR_LEN) {
488             LOGI("ie count botch (key mgmt),count %{public}u left %{public}u", count, left);
489             return -1;
490         }
491         for (i = 0; i < count; i++) {
492             data->keyMgmt = (int)((unsigned int)(data->keyMgmt) | (unsigned int)HdiKeyMgmtToAuthMgmt(pos));
493             pos += HDI_SELECTOR_LEN;
494             left -= HDI_SELECTOR_LEN;
495         }
496     } else if (left == 1) {
497         LOGI("ie too short (for capabilities)");
498         return -1;
499     }
500 
501     if (left >= HDI_POS_SECOND) {
502         data->capabilities = HdiGetBe16(pos);
503     }
504     return 0;
505 }
506 
HdiConvertIeRsn(const uint8_t * rsnIe,size_t rsnIeLen,struct HdiIeData * data)507 int HdiConvertIeRsn(const uint8_t *rsnIe, size_t rsnIeLen,
508     struct HdiIeData *data)
509 {
510     const uint8_t *pos;
511     int left;
512     int i, count;
513 
514     if (memset_s(data, sizeof(*data), 0, sizeof(*data)) != EOK) {
515         LOGE("HdiConvertIeRsn memset_s is failed");
516         return -1;
517     }
518     data->proto = HDI_PROTO_ONE;
519     data->pairwiseCipher = HDI_CIPHER_CCMP;
520     data->groupCipher = HDI_CIPHER_CCMP;
521     data->keyMgmt = HDI_KEY_MGMT;
522     data->capabilities = 0;
523     data->pmkid = NULL;
524     data->numPmkid = 0;
525     data->mgmtGroupCipher = 0;
526 
527     if (rsnIeLen == 0) {
528         return -1;
529     }
530 
531     if (rsnIeLen < sizeof(struct HdiRsnIeHdr)) {
532         LOGI("ie len too short %{public}lu", (unsigned long) rsnIeLen);
533         return -1;
534     }
535 
536     if (rsnIeLen >= HDI_POS_SIX && rsnIe[1] >= HDI_POS_FOURTH &&
537         rsnIe[1] == rsnIeLen - HDI_POS_SECOND &&
538         HdiGetBe32(&rsnIe[HDI_POS_SECOND]) == HDI_OSEN_IE_VENDOR_TYPE) {
539         pos = rsnIe + HDI_POS_SIX;
540         left = (int)(rsnIeLen - HDI_POS_SIX);
541 
542         data->groupCipher = HDI_CIPHER_GTK_NOT_USED;
543         data->hasGroup = 1;
544         data->keyMgmt = HDI_KEY_MGMT_OSEN;
545         data->proto = HDI_PROTO_THREE;
546     } else {
547         const struct HdiRsnIeHdr *hdr;
548 
549         hdr = (const struct HdiRsnIeHdr *) rsnIe;
550 
551         if (hdr->elemId != HDI_EID_RSN ||
552             hdr->len != rsnIeLen - HDI_POS_SECOND ||
553             HdiGetBe16(hdr->version) != HDI_VERSION) {
554             LOGI("malformed ie or unknown version");
555             return -1;
556         }
557 
558         pos = (const uint8_t *) (hdr + 1);
559         left = (int)(rsnIeLen - sizeof(*hdr));
560     }
561 
562     if (left >= HDI_SELECTOR_LEN) {
563         data->groupCipher = HdiRsnIdToCipherSuite(pos);
564         data->hasGroup = 1;
565         if (!HdiCheckValidGroup(data->groupCipher)) {
566             LOGI("invalid group cipher 0x%{public}x (%08x)", data->groupCipher,
567                    HdiGetBe32(pos));
568             return -1;
569         }
570         pos += HDI_SELECTOR_LEN;
571         left -= HDI_SELECTOR_LEN;
572     } else if (left > 0) {
573         LOGI("ie length mismatch, %u too much", left);
574         return -1;
575     }
576 
577     if (left >= HDI_POS_SECOND) {
578         data->pairwiseCipher = 0;
579         count = HdiGetBe16(pos);
580         pos += HDI_POS_SECOND;
581         left -= HDI_POS_SECOND;
582         if (count == 0 || count > left / HDI_SELECTOR_LEN) {
583             LOGI("ie count botch (pairwise), count %{public}u left %{public}u", count, left);
584             return -1;
585         }
586         data->hasPairwise = 1;
587         for (i = 0; i < count; i++) {
588             data->pairwiseCipher = (int)((unsigned int)(data->pairwiseCipher) |
589                 (unsigned int)HdiRsnIdToCipherSuite(pos));
590             pos += HDI_SELECTOR_LEN;
591             left -= HDI_SELECTOR_LEN;
592         }
593     } else if (left == 1) {
594         LOGI("ie too short (for key mgmt)");
595         return -1;
596     }
597 
598     if (left >= HDI_POS_SECOND) {
599         data->keyMgmt = 0;
600         count = HdiGetBe16(pos);
601         pos += HDI_POS_SECOND;
602         left -= HDI_POS_SECOND;
603         if (count == 0 || count > left / HDI_SELECTOR_LEN) {
604             LOGI("ie count botch (key mgmt) count %{public}u left %{public}u", count, left);
605             return -1;
606         }
607         for (i = 0; i < count; i++) {
608             data->keyMgmt = (int)((unsigned int)(data->keyMgmt) | (unsigned int)HdiRsnKeyMgmtToAuthMgmt(pos));
609             pos += HDI_SELECTOR_LEN;
610             left -= HDI_SELECTOR_LEN;
611         }
612     } else if (left == 1) {
613         LOGI("ie too short (for capabilities)");
614         return -1;
615     }
616 
617     if (left >= HDI_POS_SECOND) {
618         data->capabilities = HdiGetBe16(pos);
619         pos += HDI_POS_SECOND;
620         left -= HDI_POS_SECOND;
621     }
622 
623     if (left >= HDI_POS_SECOND) {
624         uint16_t numPmkid = HdiGetBe16(pos);
625         pos += HDI_POS_SECOND;
626         left -= HDI_POS_SECOND;
627         if (numPmkid > (unsigned int) left / HDI_PMKID_LEN) {
628             LOGI("PMKID underflow(numPmkid=%{public}u left=%{public}d)", numPmkid, left);
629             data->numPmkid = 0;
630             return -1;
631         } else {
632             data->numPmkid = numPmkid;
633             data->pmkid = pos;
634         }
635     }
636 
637     return 0;
638 }
639 
HdiParseIe(const uint8_t * hdiIe,size_t wpaIeLen,struct HdiIeData * data)640 int HdiParseIe(const uint8_t *hdiIe, size_t wpaIeLen,
641              struct HdiIeData *data)
642 {
643     if (wpaIeLen >= HDI_POS_FIRST && hdiIe[0] == HDI_EID_RSN) {
644         return HdiConvertIeRsn(hdiIe, wpaIeLen, data);
645     }
646     if (wpaIeLen >= HDI_POS_SIX && hdiIe[0] == HDI_EID_VENDOR_SPECIFIC &&
647         hdiIe[1] >= HDI_POS_FOURTH && HdiGetBe32(&hdiIe[HDI_POS_SECOND]) == HDI_OSEN_IE_VENDOR_TYPE) {
648         return HdiConvertIeRsn(hdiIe, wpaIeLen, data);
649     }
650     else {
651         return HdiConvertIe(hdiIe, wpaIeLen, data);
652     }
653 }
654 
HdiGetIeTxt(char * pos,char * end,const char * proto,const uint8_t * ie,size_t ieLen)655 char* HdiGetIeTxt(char *pos, char *end, const char *proto,
656                     const uint8_t *ie, size_t ieLen)
657 {
658     struct HdiIeData data;
659     char *start;
660     int ret;
661 
662     ret = HdiTxtPrintf(pos, end - pos, "[%s-", proto);
663     if (HdiCheckError(end - pos, ret)) {
664         return pos;
665     }
666     pos += ret;
667 
668     if (HdiParseIe(ie, ieLen, &data) < 0) {
669         ret = HdiTxtPrintf(pos, end - pos, "?]");
670         if (HdiCheckError(end - pos, ret)) {
671             return pos;
672         }
673         pos += ret;
674         return pos;
675     }
676 
677     start = pos;
678 
679     HDI_HANDLE_CIPHER_POS_INFO((unsigned int)(data.keyMgmt) & HDI_KEY_MGMT, ret, pos, end, "+", "%sEAP");
680     HDI_HANDLE_CIPHER_POS_INFO((unsigned int)(data.keyMgmt) & HDI_KEY_MGMT_PSK, ret, pos, end, "+", "%sPSK");
681     HDI_HANDLE_CIPHER_POS_INFO((unsigned int)(data.keyMgmt) & HDI_KEY_MGMT_HDI_NONE, ret, pos, end, "+", "%sNone");
682     HDI_HANDLE_CIPHER_POS_INFO((unsigned int)(data.keyMgmt) & HDI_KEY_MGMT_SAE, ret, pos, end, "+", "%sSAE");
683     HDI_HANDLE_CIPHER_POS_INFO((unsigned int)(data.keyMgmt) & HDI_KEY_MGMT_SUITE_B_192,
684         ret, pos, end, "+", "%sEAP-SUITE-B-192");
685     HDI_HANDLE_CIPHER_POS_INFO((unsigned int)(data.keyMgmt) & HDI_KEY_MGMT_OSEN, ret, pos, end, "+", "%sOSEN");
686     HDI_HANDLE_CIPHER_POS_INFO((unsigned int)(data.keyMgmt) & HDI_KEY_MGMT_OWE, ret, pos, end, "+", "%sOWE");
687     HDI_HANDLE_CIPHER_POS_INFO((unsigned int)(data.keyMgmt) & HDI_KEY_MGMT_PSK_SHA256, ret, pos, end, "+", "%sPSK");
688     HDI_HANDLE_CIPHER_POS_INFO((unsigned int)(data.keyMgmt) & HDI_KEY_MGMT_FT_IEEE8021X,
689         ret, pos, end, "+", "%sFT/EAP");
690     HDI_HANDLE_CIPHER_POS_INFO((unsigned int)(data.keyMgmt) & HDI_KEY_MGMT_FT_PSK, ret, pos, end, "+", "%sFT/PSK");
691     HDI_HANDLE_CIPHER_POS_INFO((unsigned int)(data.keyMgmt) & HDI_KEY_MGMT_FT_SAE, ret, pos, end, "+", "%sFT/SAE");
692     HDI_HANDLE_CIPHER_POS_INFO((unsigned int)(data.keyMgmt) & HDI_KEY_MGMT_IEEE8021X_SHA256,
693         ret, pos, end, "+", "%sEAP");
694 
695     pos = HdiGetCipherTxt(pos, end, data.pairwiseCipher);
696 
697     if ((unsigned int)data.capabilities & HDI_CAPABILITY_PREAUTH) {
698         ret = HdiTxtPrintf(pos, end - pos, "-preauth");
699         if (HdiCheckError(end - pos, ret)) {
700             return pos;
701         }
702         pos += ret;
703     }
704 
705     ret = HdiTxtPrintf(pos, end - pos, "]");
706     if (HdiCheckError(end - pos, ret)) {
707         return pos;
708     }
709     pos += ret;
710 
711     return pos;
712 }
713 
HdiGetIeExt(const uint8_t * ies,size_t len,uint8_t ext)714 const uint8_t* HdiGetIeExt(const uint8_t *ies, size_t len, uint8_t ext)
715 {
716     const struct HdiElem *elem;
717 
718     if (!ies) {
719         return NULL;
720     }
721     HDI_CHECK_ELEMENT_BY_EXTID(elem, ext, ies, len)
722         return &elem->id;
723 
724     return NULL;
725 }
726 
HdiBssGetIeExt(const uint8_t * ies,size_t len,uint8_t ext)727 const uint8_t* HdiBssGetIeExt(const uint8_t *ies, size_t len, uint8_t ext)
728 {
729     return HdiGetIeExt(ies, len, ext);
730 }
731 
HdiBufEncode(char * txt,size_t maxlen,const uint8_t * data,size_t len)732 void HdiBufEncode(char *txt, size_t maxlen, const uint8_t *data, size_t len)
733 {
734     char *end = txt + maxlen;
735     size_t i;
736 
737     for (i = 0; i < len; i++) {
738         if (txt + HDI_POS_FOURTH >= end) {
739             break;
740         }
741 
742         switch (data[i]) {
743             case '\"':
744                 *txt++ = '\\';
745                 *txt++ = '\"';
746                 break;
747             case '\\':
748                 *txt++ = '\\';
749                 *txt++ = '\\';
750                 break;
751             case '\033':
752                 *txt++ = '\\';
753                 *txt++ = 'e';
754                 break;
755             case '\n':
756                 *txt++ = '\\';
757                 *txt++ = 'n';
758                 break;
759             case '\r':
760                 *txt++ = '\\';
761                 *txt++ = 'r';
762                 break;
763             case '\t':
764                 *txt++ = '\\';
765                 *txt++ = 't';
766                 break;
767             default:
768                 if (data[i] >= HDI_POS_TT && data[i] <= HDI_POS_OTX) {
769                     *txt++ = data[i];
770                 } else {
771                     txt += HdiTxtPrintf(txt, end - txt, "\\x%02x",
772                             data[i]);
773                 }
774                 break;
775         }
776     }
777 
778     *txt = '\0';
779 }
780 
HdiSSid2Txt(const uint8_t * ssid,size_t ssidLen)781 const char* HdiSSid2Txt(const uint8_t *ssid, size_t ssidLen)
782 {
783     static char ssid_txt[SSID_MAX_LEN * HDI_POS_FOURTH + 1];
784     if (ssid == NULL) {
785         ssid_txt[0] = '\0';
786         return ssid_txt;
787     }
788 
789     HdiBufEncode(ssid_txt, sizeof(ssid_txt), ssid, ssidLen);
790     return ssid_txt;
791 }
792 
HdiGetWifiCategoryTxt(char * pos,char * end,const struct HdiElems * elems)793 char* HdiGetWifiCategoryTxt(char *pos, char* end, const struct HdiElems *elems)
794 {
795     int ret = 0;
796     if (elems->ehtCapabilities80211Be != NULL) {
797         ret = HdiTxtPrintf(pos, end - pos, "%s", "[11BE]");
798     } else if (elems->heCapabilities != NULL) {
799         ret = HdiTxtPrintf(pos, end - pos, "%s", "[11AX]");
800     }
801     if (HdiCheckError(end - pos, ret)) {
802         LOGE("HdiGetWifiCategoryTxt HdiCheckError fail");
803         return pos;
804     }
805     pos += ret;
806     return pos;
807 }
808 
IsValidHexCharAndConvert(char c)809 int8_t IsValidHexCharAndConvert(char c)
810 {
811     if (c >= '0' && c <= '9') {
812         return c - '0';
813     }
814     if (c >= 'a' && c <= 'f') {
815         return c - 'a' + ('9' - '0' + 1);
816     }
817     if (c >= 'A' && c <= 'F') {
818         return c - 'A' + ('9' - '0' + 1);
819     }
820     return -1;
821 }
822 
CheckMacIsValid(const char * macStr)823 int CheckMacIsValid(const char *macStr)
824 {
825     if (macStr == NULL || strlen(macStr) != MAC_STRING_SIZE) {
826         return -1;
827     }
828     for (int i = 0, j = 0; i < MAC_STRING_SIZE; ++i) {
829         if (j == 0 || j == 1) {
830             int v = IsValidHexCharAndConvert(macStr[i]);
831             if (v < 0) {
832                 return -1;
833             }
834             ++j;
835         } else {
836             if (macStr[i] != ':') {
837                 return -1;
838             }
839             j = 0;
840         }
841     }
842     return 0;
843 }
844 
StrSafeCopy(char * dst,unsigned len,const char * src)845 void StrSafeCopy(char *dst, unsigned len, const char *src)
846 {
847     if (dst == NULL) {
848         return;
849     }
850     if (src == NULL) {
851         dst[0] = '\0';
852         return;
853     }
854     unsigned i = 0;
855     while (i + 1 < len && src[i] != '\0') {
856         dst[i] = src[i];
857         ++i;
858     }
859     dst[i] = '\0';
860     return;
861 }
862 
HdiGetWapiTxt(char * pos,char * end,const uint8_t * ie)863 char* HdiGetWapiTxt(char *pos, char *end, const uint8_t *ie)
864 {
865     if (ie[HDI_POS_FIRST] < HDI_CAP_WAPI_BIT_OFFSET - HDI_POS_SECOND) {
866         return pos;
867     }
868 
869     char *start;
870     int ret;
871 
872     ret = HdiTxtPrintf(pos, end - pos, "[WAPI-");
873     if (HdiCheckError(end - pos, ret)) {
874         return pos;
875     }
876     pos += ret;
877 
878     start = pos;
879     uint8_t akm = ie[HDI_CAP_WAPI_BIT_OFFSET];
880     HDI_HANDLE_CIPHER_POS_INFO(akm & HDI_KEY_MGMT_WAPI_CERT_AKM, ret, pos, end, "+", "%sCERT");
881     HDI_HANDLE_CIPHER_POS_INFO(akm & HDI_KEY_MGMT_WAPI_PSK_AKM, ret, pos, end, "+", "%sPSK");
882 
883     ret = HdiTxtPrintf(pos, end - pos, "]");
884     if (HdiCheckError(end - pos, ret)) {
885         return pos;
886     }
887     pos += ret;
888 
889     return pos;
890 }