1 /** @file wifi-wps.c
2  *
3  *  @brief This file provides WPS IE and parser.
4  *
5  *  Copyright 2008-2024 NXP
6  *
7  *  SPDX-License-Identifier: BSD-3-Clause
8  *
9  */
10 
11 #include <mlan_api.h>
12 
13 #define SC_Device_Password_ID 0x1012
14 
15 const t_u8 wps_oui[4] = {0x00, 0x50, 0xf2, 0x04};
16 
17 typedef MLAN_PACK_START struct
18 {
19     t_u16 Type;
20     t_u16 Length;
21 } MLAN_PACK_END MrvlIEParamSet_t;
22 
23 /**
24  *  @brief  Parsing Device Password ID
25  *
26  *  @param message      A pointer to buffer for parsing
27  *  @param size         Length of buffer
28  *  @return             Device Password ID
29  */
wps_parser(t_u8 * message,size_t size)30 static t_u16 wps_parser(t_u8 *message, size_t size)
31 {
32     t_u16 device_password_id = 0xffff;
33     MrvlIEParamSet_t *ptlv;
34     t_u8 *plast_byte, *data;
35     t_u16 len;
36 
37     /* Beginning from Version, skip IE_ID/Length/SC_OUI field */
38     ptlv       = (MrvlIEParamSet_t *)(message + 4);
39     data       = (t_u8 *)ptlv;
40     plast_byte = (t_u8 *)(message + (t_u8)size);
41 
42     while ((void *)ptlv < (void *)plast_byte)
43     {
44 		/* Barriers are normally not required but do ensure the code is
45 		 * completely within the specified behaviour for the architecture. */
46         __asm volatile ( "dsb" ::: "memory" );
47         __asm volatile ( "isb" );
48 
49 		ptlv->Type   = mlan_ntohs(ptlv->Type);
50         ptlv->Length = mlan_ntohs(ptlv->Length);
51 
52         switch (ptlv->Type)
53         {
54             case SC_Device_Password_ID:
55                 wifi_d("SC_Device_Password_ID :: ");
56                 memcpy(&device_password_id, data, sizeof(t_u16));
57                 device_password_id = mlan_ntohs(device_password_id);
58                 wifi_d("device_password_id = 0x%x", device_password_id);
59                 break;
60             default:
61                 break;
62         }
63 
64         len = ptlv->Length + sizeof(MrvlIEParamSet_t);
65 
66         ptlv->Type   = mlan_htons(ptlv->Type);
67         ptlv->Length = mlan_htons(ptlv->Length);
68 
69         ptlv = (MrvlIEParamSet_t *)((t_u8 *)ptlv + len);
70 
71         data = (t_u8 *)ptlv;
72         data += sizeof(MrvlIEParamSet_t);
73     } /* while */
74 
75     return device_password_id;
76 }
77 
check_for_wps_ie(const t_u8 * poui,t_u8 oui_type,bool * wps_IE_exist,t_u16 * wps_session,void * element_data,unsigned element_len)78 void check_for_wps_ie(
79     const t_u8 *poui, t_u8 oui_type, bool *wps_IE_exist, t_u16 *wps_session, void *element_data, unsigned element_len)
80 {
81     if (!memcmp(poui, &wps_oui, sizeof(wps_oui) - 1U) && oui_type == wps_oui[3])
82     {
83         /* WPS IE is present in probe response. */
84         wifi_d("WPS IE :: %x:%x:%x:%x", poui[0], poui[1], poui[2], oui_type);
85 
86         *wps_IE_exist = true;
87         *wps_session  = wps_parser(element_data, element_len);
88     }
89     else if (!(*wps_IE_exist))
90     {
91         *wps_IE_exist = false;
92         *wps_session  = 0xffff;
93     }
94 }
95