1 /*
2  * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifdef ESP_SUPPLICANT
8 
9 #include "utils/includes.h"
10 #include "utils/common.h"
11 #include "common/eapol_common.h"
12 #include "rsn_supp/wpa.h"
13 #include "rsn_supp/pmksa_cache.h"
14 #include "esp_wpas_glue.h"
15 #include "esp_private/wifi.h"
16 
wpa_alloc_eapol(void * sm,u8 type,const void * data,u16 data_len,size_t * msg_len,void ** data_pos)17 u8 *wpa_alloc_eapol(void *sm, u8 type,
18                     const void *data, u16 data_len,
19                     size_t *msg_len, void **data_pos)
20 {
21     void *buffer;
22     struct ieee802_1x_hdr *hdr;
23 
24     *msg_len = sizeof(struct ieee802_1x_hdr) + data_len;
25 
26     buffer = os_malloc(*msg_len + sizeof(struct l2_ethhdr));
27 
28     if (buffer == NULL) {
29         return NULL;
30     }
31 
32     /* XXX: reserve l2_ethhdr is enough */
33     hdr = (struct ieee802_1x_hdr *)((char *)buffer + sizeof(struct l2_ethhdr));
34 
35     hdr->version = DEFAULT_EAPOL_VERSION;
36     hdr->type = type;
37     hdr->length = host_to_be16(data_len);
38 
39     if (data) {
40         memcpy(hdr + 1, data, data_len);
41     } else {
42         memset(hdr + 1, 0, data_len);
43     }
44 
45     if (data_pos) {
46         *data_pos = hdr + 1;
47     }
48 
49     return (u8 *) hdr;
50 }
51 
wpa_free_eapol(u8 * buffer)52 void wpa_free_eapol(u8 *buffer)
53 {
54     if (!buffer) {
55         return;
56     }
57     buffer = buffer - sizeof(struct l2_ethhdr);
58     os_free(buffer);
59 }
60 
wpa_ether_send(void * ctx,const u8 * dest,u16 proto,const u8 * data,size_t data_len)61 int wpa_ether_send(void *ctx, const u8 *dest, u16 proto,
62                    const u8 *data, size_t data_len)
63 {
64     void *buffer = (void *)(data - sizeof(struct l2_ethhdr));
65     struct l2_ethhdr *eth = (struct l2_ethhdr *)buffer;
66 
67     os_memcpy(eth->h_dest, dest, ETH_ALEN);
68     os_memcpy(eth->h_source, gWpaSm.own_addr, ETH_ALEN);
69     eth->h_proto = host_to_be16(proto);
70 
71     return esp_wifi_internal_tx(WIFI_IF_STA, buffer, sizeof(struct l2_ethhdr) + data_len);
72 }
73 
hostapd_send_eapol(const u8 * source,const u8 * sta_addr,const u8 * data,size_t data_len)74 int hostapd_send_eapol(const u8 *source, const u8 *sta_addr,
75 		       const u8 *data, size_t data_len)
76 {
77     void *buffer = os_malloc(data_len + sizeof(struct l2_ethhdr));
78     struct l2_ethhdr *eth = buffer;
79 
80     if (!buffer){
81         wpa_printf( MSG_DEBUG, "send_eapol, buffer=%p", buffer);
82         return -1;
83     }
84 
85     memcpy(eth->h_dest, sta_addr, ETH_ALEN);
86     memcpy(eth->h_source, source, ETH_ALEN);
87     eth->h_proto = host_to_be16(ETH_P_EAPOL);
88 
89     memcpy((char *)buffer + sizeof(struct l2_ethhdr), data, data_len);
90     esp_wifi_internal_tx(WIFI_IF_AP, buffer, sizeof(struct l2_ethhdr) + data_len);
91     os_free(buffer);
92     return 0;
93 
94 }
95 
disable_wpa_wpa2(void)96 static void disable_wpa_wpa2(void)
97 {
98     esp_wifi_sta_disable_wpa2_authmode_internal();
99 }
100 
wpa_supplicant_transition_disable(struct wpa_sm * sm,u8 bitmap)101 void wpa_supplicant_transition_disable(struct wpa_sm *sm, u8 bitmap)
102 {
103     wpa_printf(MSG_DEBUG, "TRANSITION_DISABLE %02x", bitmap);
104 
105     if  ((bitmap & TRANSITION_DISABLE_WPA3_PERSONAL) &&
106           wpa_key_mgmt_sae(sm->key_mgmt)) {
107         disable_wpa_wpa2();
108     }
109 
110     if ((bitmap & TRANSITION_DISABLE_SAE_PK) &&
111         wpa_key_mgmt_sae(sm->key_mgmt)) {
112         wpa_printf(MSG_INFO,
113             "SAE-PK: SAE authentication without PK disabled based on AP notification");
114         disable_wpa_wpa2();
115         esp_wifi_enable_sae_pk_only_mode_internal();
116     }
117 
118     if ((bitmap & TRANSITION_DISABLE_WPA3_ENTERPRISE) &&
119         wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) {
120         disable_wpa_wpa2();
121     }
122 
123     if ((bitmap & TRANSITION_DISABLE_ENHANCED_OPEN) &&
124         wpa_key_mgmt_owe(sm->key_mgmt)) {
125         esp_wifi_sta_disable_owe_trans_internal();
126     }
127 }
128 
wpa_sm_alloc_eapol(struct wpa_sm * sm,u8 type,const void * data,u16 data_len,size_t * msg_len,void ** data_pos)129 u8 *wpa_sm_alloc_eapol(struct wpa_sm *sm, u8 type,
130                        const void *data, u16 data_len,
131                        size_t *msg_len, void **data_pos)
132 {
133     return wpa_alloc_eapol(sm, type, data, data_len, msg_len, data_pos);
134 }
135 
wpa_sm_free_eapol(u8 * buffer)136 void wpa_sm_free_eapol(u8 *buffer)
137 {
138     return wpa_free_eapol(buffer);
139 }
140 
wpa_sm_deauthenticate(struct wpa_sm * sm,u8 reason_code)141 void  wpa_sm_deauthenticate(struct wpa_sm *sm, u8 reason_code)
142 {
143     /*only need send deauth frame when associated*/
144     if (WPA_SM_STATE(sm) >= WPA_ASSOCIATED) {
145         pmksa_cache_clear_current(sm);
146         wpa_deauthenticate(reason_code);
147     }
148 }
149 
150 /**
151  * mlme_setprotection - MLME-SETPROTECTION.request primitive
152  * @priv: Private driver interface data
153  * @addr: Address of the station for which to set protection (may be
154  * %NULL for group keys)
155  * @protect_type: MLME_SETPROTECTION_PROTECT_TYPE_*
156  * @key_type: MLME_SETPROTECTION_KEY_TYPE_*
157  * Returns: 0 on success, -1 on failure
158  *
159  * This is an optional function that can be used to set the driver to
160  * require protection for Tx and/or Rx frames. This uses the layer
161  * interface defined in IEEE 802.11i-2004 clause 10.3.22.1
162  * (MLME-SETPROTECTION.request). Many drivers do not use explicit
163  * set protection operation; instead, they set protection implicitly
164  * based on configured keys.
165  */
wpa_sm_mlme_setprotection(struct wpa_sm * sm,const u8 * addr,int protect_type,int key_type)166 int  wpa_sm_mlme_setprotection(struct wpa_sm *sm, const u8 *addr,
167                                int protect_type, int key_type)
168 {
169     return 0;
170 }
171 
172 /*
173  *use above two functions to get wpa_ie and rsn_ie, then don't need wpa_sm_get_beacon_ie function
174 */
wpa_sm_get_beacon_ie(struct wpa_sm * sm)175 int  wpa_sm_get_beacon_ie(struct wpa_sm *sm)
176 {
177     return 0;
178 }
179 
180 /**
181  * wpa_supplicant_disassociate - Disassociate the current connection
182  * @wpa_s: Pointer to wpa_supplicant data
183  * @reason_code: IEEE 802.11 reason code for the disassociate frame
184  *
185  * This function is used to request %wpa_supplicant to disassociate with the
186  * current AP.
187  */
wpa_sm_disassociate(struct wpa_sm * sm,int reason_code)188 void  wpa_sm_disassociate(struct wpa_sm *sm, int reason_code)
189 {
190     /*check if need clear internal state and data value*/
191 }
192 #endif
193