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