1 /*
2  *  Copyright 2008-2024 NXP
3  *
4  *  SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 /** @file wifi_nxp_wps.h
9  *
10  *  @brief WPS - WiFi Protected Setup
11  *
12  *  Wi-Fi Protected Setup (WPS) is a standard for easy and secure wireless
13  *  network set up and connections. Using this standard, wireless clients
14  *  can associate with the WPS enabled access point by entering the same
15  *  PIN at client and AP end or by pushing a pushbutton on both. This eliminates
16  *  the need for manually entering the security configuration on the client side.
17  *
18  *  Two methods that are supported by SDK are:
19  *
20  *  \li PIN Method: In this method the same PIN (Personal Identification Number)
21  *  is entered on the wireless client and access point. The PIN can be static
22  *  or dynamically generated on any of the AP or wireless client.
23  *  \li PBC Method: in which the user simply has to push a button, either
24  *  an actual or virtual one, on both the AP and wireless client.
25  *
26  *  \section wps_usage Usage
27  *  In a typical implementation WPS thread is started by calling \ref wps_start.
28  *  A valid initialized \ref wps_config structure needs to be passed to this
29  *  function. This structure contains a callback handler which is invoked by the
30  *  WPS thread on occurrence of various events. Once the WPS thread is started,
31  *  commands can be sent to it using \ref wps_connect function. Typically
32  *  these commands can be start PIN session, or start a pushbutton session. This
33  *  requires passing \ref wps_session_command structure that contains a valid
34  *  \ref wlan_scan_result that contains network information for a WPS enabled
35  *  wireless network. On successful WPS session, callback handler is invoked with
36  *  \ref WPS_SESSION_SUCCESSFUL event with \ref wlan_network structure that
37  *  contains all the security information for the network with which WPS
38  *  session was attempted. After this \ref wps_stop should be called to
39  *  terminate the WPS thread.
40  *
41  *  \note WPS implementation lets application decide PIN policy. PIN could either
42  *  be generated by the application, or by the access point or can be statically
43  *  generated at device manufacturing time. \ref wps_generate_pin and \ref
44  *  wps_validate_pin utility functions can be used by the application to generate
45  *  and validate PIN.
46  *
47  *  \note WPS thread internally uses multiple dynamic allocations. Please do not
48  *  reduce the heap size below 64KB if the application wishes to use WPS.
49  *
50  */
51 
52 #ifndef WPS_H
53 #define WPS_H
54 
55 #include <wlan.h>
56 #include <wmlog.h>
57 
58 #if (CONFIG_WPA2_ENTP) && !(CONFIG_WPS2)
59 #error "CONFIG_WPA2_ENTP is enabled, but CONFIG_WPS2 is not, enable it from wifi_config.h"
60 #endif
61 
62 #if CONFIG_WPS_DEBUG
63 #define wps_d(...) wmlog("wps", ##__VA_ARGS__)
64 #else
65 #define wps_d(...)
66 #endif
67 
68 /** MAC to string */
69 #ifndef MAC2STR
70 #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
71 #endif
72 /** MAC string */
73 #ifndef MACSTR
74 #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
75 #endif
76 
77 #if CONFIG_WPS_DEBUG
78 /** ENTER */
79 #ifndef ENTER
80 #define ENTER() PRINTF("Enter: %s : %i\r\n", __FUNCTION__, __LINE__)
81 // #define ENTER()    PRINTF("Enter: %s, %s:%i\r\n", __FUNCTION__, __FILE__, __LINE__)
82 #endif
83 
84 /** LEAVE */
85 #ifndef LEAVE
86 #define LEAVE() PRINTF("Leave: %s : %i\r\n", __FUNCTION__, __LINE__)
87 // #define LEAVE()    PRINTF("Leave: %s, %s:%i\r\n", __FUNCTION__, __FILE__, __LINE__)
88 #endif
89 #else
90 #ifndef ENTER
91 #define ENTER()
92 #endif
93 #ifndef LEAVE
94 #define LEAVE()
95 #endif
96 #endif
97 
98 #ifndef BIT
99 #define BIT(x) (1 << (x))
100 #endif
101 
102 #define PROV_NON_SESSION_ATTEMPT  0
103 #define PROV_WPS_SESSION_ATTEMPT  1
104 #define PROV_ENTP_SESSION_ATTEMPT 2
105 
106 #if CONFIG_WPS_DEBUG
wps_hexdump(const char * title,const unsigned char * data,size_t len)107 static inline void wps_hexdump(const char *title, const unsigned char *data, size_t len)
108 {
109     int i, j;
110     unsigned char *offset;
111     // #ifndef ENTER
112     offset = (unsigned char *)data;
113     PRINTF("[wps] %s - hexdump(len=%lu):\r\n", title, (unsigned long)len);
114     // #define ENTER()    PRINTF("Enter: %s : %i\r\n", __FUNCTION__, __LINE__)
115     for (i = 0; i < len / 16; i++)
116     {
117         for (j = 0; j < 16; j++)
118             PRINTF("%02x  ", offset[j]);
119         PRINTF("\r\n");
120         offset += 16;
121     }
122     i = len % 16;
123     for (j = 0; j < i; j++)
124         PRINTF("%02x  ", offset[j]);
125     PRINTF("\r\n");
126 }
127 #else
wps_hexdump(const char * title,const unsigned char * data,size_t len)128 static inline void wps_hexdump(const char *title, const unsigned char *data, size_t len)
129 {
130 }
131 #endif
132 #define PM3_BSS
133 
134 #if defined(__arm__)
135 #if defined(__ARMCC_VERSION)
136 #define LWIP_TIMEVAL_PRIVATE 1
137 #else
138 #define LWIP_TIMEVAL_PRIVATE 0
139 #endif
140 #ifndef LWIP_SOCKET_SELECT
141 #define LWIP_SOCKET_SELECT 0
142 #endif
143 #endif
144 
145 /** enum : WPS session commands */
146 enum wps_session_command
147 {
148     /** Command to start WPS PIN session */
149     CMD_WPS_PIN = 0,
150     /** Command to start WPS PBC session */
151     CMD_WPS_PBC
152 };
153 
154 /** enum : WPS events */
155 enum wps_event
156 {
157     /** WPS thread started */
158     WPS_STARTED = 0,
159     /** WPS PBC/PIN Session started */
160     WPS_SESSION_STARTED,
161     /** WPS PIN checksum failed */
162     WPS_SESSION_PIN_CHKSUM_FAILED,
163     /** WPS Session aborted */
164     WPS_SESSION_ABORTED,
165     /** WPS Session registration timeout */
166     WPS_SESSION_TIMEOUT,
167     /** WPS Session attempt successful */
168     WPS_SESSION_SUCCESSFUL,
169     /** WPS Session failed */
170     WPS_SESSION_FAILED,
171     /** WPS thread stopped */
172     WPS_FINISHED
173 };
174 
175 /** Enum that indicates type of WPS session
176  *   either a push button or a PIN based session is
177  *   determined by value fo this enum
178  */
179 enum wps_session_types
180 {
181     /** WPS session is not active */
182     WPS_SESSION_INACTIVE = 0xffff,
183     /** WPS Push Button session active */
184     WPS_SESSION_PBC = 0x0004,
185     /** WPS PIN session active */
186     WPS_SESSION_PIN = 0x0000,
187 };
188 
189 /**
190  * This struct is passed to wps_start(). The user must initialize it
191  * with parameters as described inline.
192  */
193 struct wps_config
194 {
195     /** Enrollee: 1, Registrar: 2, WiFi Direct mode:4 */
196     uint8_t role;
197     /** PIN Generator - Enrollee or Registrar */
198     uint8_t pin_generator;
199     /** version */
200     uint8_t version;
201     /** version */
202     uint8_t version2;
203     /** Device name */
204     uint8_t device_name[32];
205     /** Manufacture */
206     uint8_t manufacture[64];
207     /** Model name */
208     uint8_t model_name[32];
209     /** Model number */
210     uint8_t model_number[32];
211     /** Serial number */
212     uint8_t serial_number[32];
213     /** Config methods */
214     uint16_t config_methods;
215     /** Primary Device category*/
216     uint16_t primary_dev_category;
217     /** Primary Device subcategory*/
218     uint16_t primary_dev_subcategory;
219     /** RF bands */
220     uint8_t rf_bands;
221     /** OS Version */
222     uint32_t os_version;
223     /** WPS message max retry */
224     uint8_t wps_msg_max_retry;
225     /** WPS message timeout */
226     uint32_t wps_msg_timeout;
227     /** PIN length */
228     uint16_t pin_len;
229     /** WPS callback */
230     int (*wps_callback)(enum wps_event event, void *data, uint16_t len);
231     /** session attempt PROV_NON_SESSION_ATTEMPT/PROV_WPS_SESSION_ATTEMPT/PROV_ENTP_SESSION_ATTEMPT */
232     uint8_t prov_session;
233 };
234 
235 /** Starts WPS thread and enables commands delivery
236  *
237  * \param wps_conf A pointer to WPS custom configuration
238  *
239  * \returns WM_SUCCESS if successful, -WM_FAIL otherwise
240  */
241 int wps_start(struct wps_config *wps_conf);
242 
243 /** Connect to WPS enabled AP
244  *
245  * Connect to a WPS enabled AP. This function is typically called whenever
246  * the users pushes the wps button or enters wps pin.
247  *
248  * \param pbc Set to 1 if Push-button session is desired
249  * \param pin Ignore if pbc is 1. If pbc is 0, this indicates the pin that
250  * should be used. The pin can be 4 or 8 digits.
251  * \param res The WPS enabled AP to connect to.
252  *
253  * \returns WM_SUCCESS if successful, -WM_FAIL otherwise
254  */
255 int wps_connect(enum wps_session_command pbc, uint32_t pin, struct wlan_scan_result *res);
256 
257 /** Generate 8 digit WPS PIN value with random number generator
258  *
259  * \param wps_pin Generated 8 digit WPS PIN value
260  *
261  * \returns WM_SUCCESS if successful, -WM_FAIL otherwise
262  */
263 int wps_generate_pin(uint32_t *wps_pin);
264 
265 /**Validate checksum of PIN
266  *
267  * \param wps_pin WPS PIN value
268  *
269  * \returns WM_SUCCESS if successful, -WM_FAIL otherwise
270  **/
271 int wps_validate_pin(uint32_t wps_pin);
272 
273 /** Deletes WPS thread and message queue
274  *
275  * \returns WM_SUCCESS if successful, -WM_FAIL otherwise
276  */
277 int wps_stop();
278 #endif
279