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 (a << HDI_POS_FOURTH) | 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 (ciphers & HDI_CIPHER_CCMP_256) {
185         HDI_HANDLE_CIPHER_INFO(ret, start, end, delim, "%sCCMP-256");
186     }
187     if (ciphers & HDI_CIPHER_GCMP_256) {
188         HDI_HANDLE_CIPHER_INFO(ret, start, end, delim, "%sGCMP-256");
189     }
190     if (ciphers & HDI_CIPHER_CCMP) {
191         HDI_HANDLE_CIPHER_INFO(ret, start, end, delim, "%sCCMP");
192     }
193     if (ciphers & HDI_CIPHER_GCMP) {
194         HDI_HANDLE_CIPHER_INFO(ret, start, end, delim, "%sGCMP");
195     }
196     if (ciphers & HDI_CIPHER_TKIP) {
197         HDI_HANDLE_CIPHER_INFO(ret, start, end, delim, "%sTKIP");
198     }
199     if (ciphers & HDI_CIPHER_AES_128_CMAC) {
200         HDI_HANDLE_CIPHER_INFO(ret, start, end, delim, "%sAES-128-CMAC");
201     }
202     if (ciphers & HDI_CIPHER_BIP_GMAC_128) {
203         HDI_HANDLE_CIPHER_INFO(ret, start, end, delim, "%sBIP-GMAC-128");
204     }
205     if (ciphers & HDI_CIPHER_BIP_GMAC_256) {
206         HDI_HANDLE_CIPHER_INFO(ret, start, end, delim, "%sBIP-GMAC-256");
207     }
208     if (ciphers & HDI_CIPHER_BIP_CMAC_256) {
209         HDI_HANDLE_CIPHER_INFO(ret, start, end, delim, "%sBIP-CMAC-256");
210     }
211     if (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     return 0;
345 }
346 
HdiGetIe(const uint8_t * ies,size_t len,uint8_t eid)347 const uint8_t* HdiGetIe(const uint8_t *ies, size_t len, uint8_t eid)
348 {
349     const struct HdiElem *elem;
350 
351     if (!ies) {
352         return NULL;
353     }
354 
355     HDI_CHECK_ELEMENT_BY_ID(elem, eid, ies, len)
356         return &elem->id;
357 
358     return NULL;
359 }
360 
HdiBssGetIe(const uint8_t * ies,size_t len,uint8_t ie)361 const uint8_t* HdiBssGetIe(const uint8_t *ies, size_t len, uint8_t ie)
362 {
363     return HdiGetIe(ies, len, ie);
364 }
365 
HdiBssGetVendorIe(const uint8_t * ies,size_t len,uint32_t vendorType)366 const uint8_t *HdiBssGetVendorIe(const uint8_t *ies, size_t len, uint32_t vendorType)
367 {
368     const struct HdiElem *elem;
369     HDI_CHECK_ELEMENT_BY_ID(elem, HDI_EID_VENDOR_SPECIFIC, ies, len) {
370         if (elem->datalen >= HDI_POS_FOURTH && vendorType == HdiGetBe32(elem->data)) {
371             return &elem->id;
372         }
373     }
374 
375     return NULL;
376 }
377 
HdiBssGetVendorBeacon(const uint8_t * ies,size_t len,size_t beaconIeLen,uint32_t vendorType)378 const uint8_t* HdiBssGetVendorBeacon(const uint8_t *ies, size_t len, size_t beaconIeLen, uint32_t vendorType)
379 {
380     const struct HdiElem *elem;
381 
382     if (beaconIeLen == 0) {
383         return NULL;
384     }
385 
386     ies += len;
387 
388     HDI_CHECK_ELEMENT_BY_ID(elem, HDI_EID_VENDOR_SPECIFIC, ies, beaconIeLen) {
389         if (elem->datalen >= HDI_POS_FOURTH && vendorType == HdiGetBe32(elem->data)) {
390             return &elem->id;
391         }
392     }
393 
394     return NULL;
395 }
396 
HdiCheckValidWise(int cipher)397 int HdiCheckValidWise(int cipher)
398 {
399     return cipher == HDI_CIPHER_CCMP_256 ||
400         cipher == HDI_CIPHER_GCMP_256 ||
401         cipher == HDI_CIPHER_CCMP ||
402         cipher == HDI_CIPHER_GCMP ||
403         cipher == HDI_CIPHER_TKIP;
404 }
405 
HdiCheckValidGroup(int cipher)406 int HdiCheckValidGroup(int cipher)
407 {
408     return HdiCheckValidWise(cipher) ||
409         cipher == HDI_CIPHER_GTK_NOT_USED;
410 }
411 
HdiConvertIe(const uint8_t * hdiIe,size_t wpaIeLen,struct HdiIeData * data)412 int HdiConvertIe(const uint8_t *hdiIe, size_t wpaIeLen,
413              struct HdiIeData *data)
414 {
415     const struct HdiIeHdr *hdr;
416     const uint8_t *pos;
417     int left;
418     int i, count;
419 
420     (void)memset_s(data, sizeof(*data), 0, sizeof(*data));
421     data->proto = HDI_PROTO_DEFAULT;
422     data->pairwiseCipher = HDI_CIPHER_TKIP;
423     data->groupCipher = HDI_CIPHER_TKIP;
424     data->keyMgmt = HDI_KEY_MGMT;
425     data->capabilities = 0;
426     data->pmkid = NULL;
427     data->numPmkid = 0;
428     data->mgmtGroupCipher = 0;
429 
430     if (wpaIeLen < sizeof(struct HdiIeHdr)) {
431         LOGI("ie len too short %{public}lu", (unsigned long) wpaIeLen);
432         return -1;
433     }
434 
435     hdr = (const struct HdiIeHdr *) hdiIe;
436 
437     if (hdr->elemId != HDI_EID_VENDOR_SPECIFIC ||
438         hdr->len != wpaIeLen - HDI_POS_SECOND ||
439         HDI_GET_RSN_ID(hdr->oui) != HDI_OUI_TYPE ||
440         HdiGetBe16(hdr->version) != HDI_VERSION) {
441         LOGI("malformed ie or unknown version");
442         return -1;
443     }
444 
445     pos = (const uint8_t *) (hdr + 1);
446     left = (int)(wpaIeLen - sizeof(*hdr));
447 
448     if (left >= HDI_SELECTOR_LEN) {
449         data->groupCipher = HdiRsnIdToCipher(pos);
450         pos += HDI_SELECTOR_LEN;
451         left -= HDI_SELECTOR_LEN;
452     } else if (left > 0) {
453         LOGI("ie length mismatch, %{public}u too much", left);
454         return -1;
455     }
456 
457     if (left >= HDI_POS_SECOND) {
458         data->pairwiseCipher = 0;
459         count = HdiGetBe16(pos);
460         pos += HDI_POS_SECOND;
461         left -= HDI_POS_SECOND;
462         if (count == 0 || count > left / HDI_SELECTOR_LEN) {
463             LOGI("ie count botch (pairwise), count %{public}u left %{public}u", count, left);
464             return -1;
465         }
466         for (i = 0; i < count; i++) {
467             data->pairwiseCipher |= HdiRsnIdToCipher(pos);
468             pos += HDI_SELECTOR_LEN;
469             left -= HDI_SELECTOR_LEN;
470         }
471     } else if (left == 1) {
472         LOGI("ie too short (for key mgmt)");
473         return -1;
474     }
475 
476     if (left >= HDI_POS_SECOND) {
477         data->keyMgmt = 0;
478         count = HdiGetBe16(pos);
479         pos += HDI_POS_SECOND;
480         left -= HDI_POS_SECOND;
481         if (count == 0 || count > left / HDI_SELECTOR_LEN) {
482             LOGI("ie count botch (key mgmt),count %{public}u left %{public}u", count, left);
483             return -1;
484         }
485         for (i = 0; i < count; i++) {
486             data->keyMgmt |= HdiKeyMgmtToAuthMgmt(pos);
487             pos += HDI_SELECTOR_LEN;
488             left -= HDI_SELECTOR_LEN;
489         }
490     } else if (left == 1) {
491         LOGI("ie too short (for capabilities)");
492         return -1;
493     }
494 
495     if (left >= HDI_POS_SECOND) {
496         data->capabilities = HdiGetBe16(pos);
497     }
498     return 0;
499 }
500 
HdiConvertIeRsn(const uint8_t * rsnIe,size_t rsnIeLen,struct HdiIeData * data)501 int HdiConvertIeRsn(const uint8_t *rsnIe, size_t rsnIeLen,
502     struct HdiIeData *data)
503 {
504     const uint8_t *pos;
505     int left;
506     int i, count;
507 
508     (void)memset_s(data, sizeof(*data), 0, sizeof(*data));
509     data->proto = HDI_PROTO_ONE;
510     data->pairwiseCipher = HDI_CIPHER_CCMP;
511     data->groupCipher = HDI_CIPHER_CCMP;
512     data->keyMgmt = HDI_KEY_MGMT;
513     data->capabilities = 0;
514     data->pmkid = NULL;
515     data->numPmkid = 0;
516     data->mgmtGroupCipher = 0;
517 
518     if (rsnIeLen == 0) {
519         return -1;
520     }
521 
522     if (rsnIeLen < sizeof(struct HdiRsnIeHdr)) {
523         LOGI("ie len too short %{public}lu", (unsigned long) rsnIeLen);
524         return -1;
525     }
526 
527     if (rsnIeLen >= HDI_POS_SIX && rsnIe[1] >= HDI_POS_FOURTH &&
528         rsnIe[1] == rsnIeLen - HDI_POS_SECOND &&
529         HdiGetBe32(&rsnIe[HDI_POS_SECOND]) == HDI_OSEN_IE_VENDOR_TYPE) {
530         pos = rsnIe + HDI_POS_SIX;
531         left = rsnIeLen - HDI_POS_SIX;
532 
533         data->groupCipher = HDI_CIPHER_GTK_NOT_USED;
534         data->hasGroup = 1;
535         data->keyMgmt = HDI_KEY_MGMT_OSEN;
536         data->proto = HDI_PROTO_THREE;
537     } else {
538         const struct HdiRsnIeHdr *hdr;
539 
540         hdr = (const struct HdiRsnIeHdr *) rsnIe;
541 
542         if (hdr->elemId != HDI_EID_RSN ||
543             hdr->len != rsnIeLen - HDI_POS_SECOND ||
544             HdiGetBe16(hdr->version) != HDI_VERSION) {
545             LOGI("malformed ie or unknown version");
546             return -1;
547         }
548 
549         pos = (const uint8_t *) (hdr + 1);
550         left = rsnIeLen - sizeof(*hdr);
551     }
552 
553     if (left >= HDI_SELECTOR_LEN) {
554         data->groupCipher = HdiRsnIdToCipherSuite(pos);
555         data->hasGroup = 1;
556         if (!HdiCheckValidGroup(data->groupCipher)) {
557             LOGI("invalid group cipher 0x%{public}x (%08x)", data->groupCipher,
558                    HdiGetBe32(pos));
559             return -1;
560         }
561         pos += HDI_SELECTOR_LEN;
562         left -= HDI_SELECTOR_LEN;
563     } else if (left > 0) {
564         LOGI("ie length mismatch, %u too much", left);
565         return -1;
566     }
567 
568     if (left >= HDI_POS_SECOND) {
569         data->pairwiseCipher = 0;
570         count = HdiGetBe16(pos);
571         pos += HDI_POS_SECOND;
572         left -= HDI_POS_SECOND;
573         if (count == 0 || count > left / HDI_SELECTOR_LEN) {
574             LOGI("ie count botch (pairwise), count %{public}u left %{public}u", count, left);
575             return -1;
576         }
577         data->hasPairwise = 1;
578         for (i = 0; i < count; i++) {
579             data->pairwiseCipher |= HdiRsnIdToCipherSuite(pos);
580             pos += HDI_SELECTOR_LEN;
581             left -= HDI_SELECTOR_LEN;
582         }
583     } else if (left == 1) {
584         LOGI("ie too short (for key mgmt)");
585         return -1;
586     }
587 
588     if (left >= HDI_POS_SECOND) {
589         data->keyMgmt = 0;
590         count = HdiGetBe16(pos);
591         pos += HDI_POS_SECOND;
592         left -= HDI_POS_SECOND;
593         if (count == 0 || count > left / HDI_SELECTOR_LEN) {
594             LOGI("ie count botch (key mgmt) count %{public}u left %{public}u", count, left);
595             return -1;
596         }
597         for (i = 0; i < count; i++) {
598             data->keyMgmt |= HdiRsnKeyMgmtToAuthMgmt(pos);
599             pos += HDI_SELECTOR_LEN;
600             left -= HDI_SELECTOR_LEN;
601         }
602     } else if (left == 1) {
603         LOGI("ie too short (for capabilities)");
604         return -1;
605     }
606 
607     if (left >= HDI_POS_SECOND) {
608         data->capabilities = HdiGetBe16(pos);
609         pos += HDI_POS_SECOND;
610         left -= HDI_POS_SECOND;
611     }
612 
613     if (left >= HDI_POS_SECOND) {
614         uint16_t numPmkid = HdiGetBe16(pos);
615         pos += HDI_POS_SECOND;
616         left -= HDI_POS_SECOND;
617         if (numPmkid > (unsigned int) left / HDI_PMKID_LEN) {
618             LOGI("PMKID underflow(numPmkid=%{public}u left=%{public}d)", numPmkid, left);
619             data->numPmkid = 0;
620             return -1;
621         } else {
622             data->numPmkid = numPmkid;
623             data->pmkid = pos;
624         }
625     }
626 
627     return 0;
628 }
629 
HdiParseIe(const uint8_t * hdiIe,size_t wpaIeLen,struct HdiIeData * data)630 int HdiParseIe(const uint8_t *hdiIe, size_t wpaIeLen,
631              struct HdiIeData *data)
632 {
633     if (wpaIeLen >= HDI_POS_FIRST && hdiIe[0] == HDI_EID_RSN) {
634         return HdiConvertIeRsn(hdiIe, wpaIeLen, data);
635     }
636     if (wpaIeLen >= HDI_POS_SIX && hdiIe[0] == HDI_EID_VENDOR_SPECIFIC &&
637         hdiIe[1] >= HDI_POS_FOURTH && HdiGetBe32(&hdiIe[HDI_POS_SECOND]) == HDI_OSEN_IE_VENDOR_TYPE) {
638         return HdiConvertIeRsn(hdiIe, wpaIeLen, data);
639     }
640     else {
641         return HdiConvertIe(hdiIe, wpaIeLen, data);
642     }
643 }
644 
HdiGetIeTxt(char * pos,char * end,const char * proto,const uint8_t * ie,size_t ieLen)645 char* HdiGetIeTxt(char *pos, char *end, const char *proto,
646                     const uint8_t *ie, size_t ieLen)
647 {
648     struct HdiIeData data;
649     char *start;
650     int ret;
651 
652     ret = HdiTxtPrintf(pos, end - pos, "[%s-", proto);
653     if (HdiCheckError(end - pos, ret)) {
654         return pos;
655     }
656     pos += ret;
657 
658     if (HdiParseIe(ie, ieLen, &data) < 0) {
659         ret = HdiTxtPrintf(pos, end - pos, "?]");
660         if (HdiCheckError(end - pos, ret)) {
661             return pos;
662         }
663         pos += ret;
664         return pos;
665     }
666 
667     start = pos;
668 
669     HDI_HANDLE_CIPHER_POS_INFO(data.keyMgmt & HDI_KEY_MGMT, ret, pos, end, "+", "%sEAP");
670     HDI_HANDLE_CIPHER_POS_INFO(data.keyMgmt & HDI_KEY_MGMT_PSK, ret, pos, end, "+", "%sPSK");
671     HDI_HANDLE_CIPHER_POS_INFO(data.keyMgmt & HDI_KEY_MGMT_HDI_NONE, ret, pos, end, "+", "%sNone");
672     HDI_HANDLE_CIPHER_POS_INFO(data.keyMgmt & HDI_KEY_MGMT_SAE, ret, pos, end, "+", "%sSAE");
673     HDI_HANDLE_CIPHER_POS_INFO(data.keyMgmt & HDI_KEY_MGMT_SUITE_B_192, ret, pos, end, "+", "%sEAP-SUITE-B-192");
674     HDI_HANDLE_CIPHER_POS_INFO(data.keyMgmt & HDI_KEY_MGMT_OSEN, ret, pos, end, "+", "%sOSEN");
675     HDI_HANDLE_CIPHER_POS_INFO(data.keyMgmt & HDI_KEY_MGMT_OWE, ret, pos, end, "+", "%sOWE");
676     HDI_HANDLE_CIPHER_POS_INFO(data.keyMgmt & HDI_KEY_MGMT_PSK_SHA256, ret, pos, end, "+", "%sPSK");
677     HDI_HANDLE_CIPHER_POS_INFO(data.keyMgmt & HDI_KEY_MGMT_FT_IEEE8021X, ret, pos, end, "+", "%sFT/EAP");
678     HDI_HANDLE_CIPHER_POS_INFO(data.keyMgmt & HDI_KEY_MGMT_FT_PSK, ret, pos, end, "+", "%sFT/PSK");
679     HDI_HANDLE_CIPHER_POS_INFO(data.keyMgmt & HDI_KEY_MGMT_FT_SAE, ret, pos, end, "+", "%sFT/SAE");
680 
681     pos = HdiGetCipherTxt(pos, end, data.pairwiseCipher);
682 
683     if ((unsigned int)data.capabilities & HDI_CAPABILITY_PREAUTH) {
684         ret = HdiTxtPrintf(pos, end - pos, "-preauth");
685         if (HdiCheckError(end - pos, ret)) {
686             return pos;
687         }
688         pos += ret;
689     }
690 
691     ret = HdiTxtPrintf(pos, end - pos, "]");
692     if (HdiCheckError(end - pos, ret)) {
693         return pos;
694     }
695     pos += ret;
696 
697     return pos;
698 }
699 
HdiGetIeExt(const uint8_t * ies,size_t len,uint8_t ext)700 const uint8_t* HdiGetIeExt(const uint8_t *ies, size_t len, uint8_t ext)
701 {
702     const struct HdiElem *elem;
703 
704     if (!ies) {
705         return NULL;
706     }
707     HDI_CHECK_ELEMENT_BY_EXTID(elem, ext, ies, len)
708         return &elem->id;
709 
710     return NULL;
711 }
712 
HdiBssGetIeExt(const uint8_t * ies,size_t len,uint8_t ext)713 const uint8_t* HdiBssGetIeExt(const uint8_t *ies, size_t len, uint8_t ext)
714 {
715     return HdiGetIeExt(ies, len, ext);
716 }
717 
HdiBufEncode(char * txt,size_t maxlen,const uint8_t * data,size_t len)718 void HdiBufEncode(char *txt, size_t maxlen, const uint8_t *data, size_t len)
719 {
720     char *end = txt + maxlen;
721     size_t i;
722 
723     for (i = 0; i < len; i++) {
724         if (txt + HDI_POS_FOURTH >= end) {
725             break;
726         }
727 
728         switch (data[i]) {
729             case '\"':
730                 *txt++ = '\\';
731                 *txt++ = '\"';
732                 break;
733             case '\\':
734                 *txt++ = '\\';
735                 *txt++ = '\\';
736                 break;
737             case '\033':
738                 *txt++ = '\\';
739                 *txt++ = 'e';
740                 break;
741             case '\n':
742                 *txt++ = '\\';
743                 *txt++ = 'n';
744                 break;
745             case '\r':
746                 *txt++ = '\\';
747                 *txt++ = 'r';
748                 break;
749             case '\t':
750                 *txt++ = '\\';
751                 *txt++ = 't';
752                 break;
753             default:
754                 if (data[i] >= HDI_POS_TT && data[i] <= HDI_POS_OTX) {
755                     *txt++ = data[i];
756                 } else {
757                     txt += HdiTxtPrintf(txt, end - txt, "\\x%02x",
758                             data[i]);
759                 }
760                 break;
761         }
762     }
763 
764     *txt = '\0';
765 }
766 
HdiSSid2Txt(const uint8_t * ssid,size_t ssidLen)767 const char* HdiSSid2Txt(const uint8_t *ssid, size_t ssidLen)
768 {
769     static char ssid_txt[SSID_MAX_LEN * HDI_POS_FOURTH + 1];
770     if (ssid == NULL) {
771         ssid_txt[0] = '\0';
772         return ssid_txt;
773     }
774 
775     HdiBufEncode(ssid_txt, sizeof(ssid_txt), ssid, ssidLen);
776     return ssid_txt;
777 }
778 
HdiGetWifiCategoryTxt(char * pos,char * end,const struct HdiElems * elems)779 char* HdiGetWifiCategoryTxt(char *pos, char* end, const struct HdiElems *elems)
780 {
781     int ret = 0;
782     if (elems->ehtCapabilities80211Be != NULL) {
783         ret = HdiTxtPrintf(pos, end - pos, "%s", "[11BE]");
784     } else if (elems->heCapabilities != NULL) {
785         ret = HdiTxtPrintf(pos, end - pos, "%s", "[11AX]");
786     }
787     if (HdiCheckError(end - pos, ret)) {
788         LOGE("HdiGetWifiCategoryTxt HdiCheckError fail");
789         return pos;
790     }
791     pos += ret;
792     return pos;
793 }
794 
IsValidHexCharAndConvert(char c)795 int8_t IsValidHexCharAndConvert(char c)
796 {
797     if (c >= '0' && c <= '9') {
798         return c - '0';
799     }
800     if (c >= 'a' && c <= 'f') {
801         return c - 'a' + ('9' - '0' + 1);
802     }
803     if (c >= 'A' && c <= 'F') {
804         return c - 'A' + ('9' - '0' + 1);
805     }
806     return -1;
807 }
808 
CheckMacIsValid(const char * macStr)809 int CheckMacIsValid(const char *macStr)
810 {
811     if (macStr == NULL || strlen(macStr) != MAC_STRING_SIZE) {
812         return -1;
813     }
814     for (int i = 0, j = 0; i < MAC_STRING_SIZE; ++i) {
815         if (j == 0 || j == 1) {
816             int v = IsValidHexCharAndConvert(macStr[i]);
817             if (v < 0) {
818                 return -1;
819             }
820             ++j;
821         } else {
822             if (macStr[i] != ':') {
823                 return -1;
824             }
825             j = 0;
826         }
827     }
828     return 0;
829 }
830 
StrSafeCopy(char * dst,unsigned len,const char * src)831 void StrSafeCopy(char *dst, unsigned len, const char *src)
832 {
833     if (dst == NULL) {
834         return;
835     }
836     if (src == NULL) {
837         dst[0] = '\0';
838         return;
839     }
840     unsigned i = 0;
841     while (i + 1 < len && src[i] != '\0') {
842         dst[i] = src[i];
843         ++i;
844     }
845     dst[i] = '\0';
846     return;
847 }
848 
HdiGetWapiTxt(char * pos,char * end,const uint8_t * ie)849 char* HdiGetWapiTxt(char *pos, char *end, const uint8_t *ie)
850 {
851     if (ie[HDI_POS_FIRST] < HDI_CAP_WAPI_BIT_OFFSET - HDI_POS_SECOND) {
852         return pos;
853     }
854 
855     char *start;
856     int ret;
857 
858     ret = HdiTxtPrintf(pos, end - pos, "[WAPI-");
859     if (HdiCheckError(end - pos, ret)) {
860         return pos;
861     }
862     pos += ret;
863 
864     start = pos;
865     uint8_t akm = ie[HDI_CAP_WAPI_BIT_OFFSET];
866     HDI_HANDLE_CIPHER_POS_INFO(akm & HDI_KEY_MGMT_WAPI_CERT_AKM, ret, pos, end, "+", "%sCERT");
867     HDI_HANDLE_CIPHER_POS_INFO(akm & HDI_KEY_MGMT_WAPI_PSK_AKM, ret, pos, end, "+", "%sPSK");
868 
869     ret = HdiTxtPrintf(pos, end - pos, "]");
870     if (HdiCheckError(end - pos, ret)) {
871         return pos;
872     }
873     pos += ret;
874 
875     return pos;
876 }