/src/hostap/tests/fuzzing/eapol-key-supp/eapol-key-supp.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Testing tool for EAPOL-Key Supplicant routines |
3 | | * Copyright (c) 2006-2019, Jouni Malinen <j@w1.fi> |
4 | | * |
5 | | * This software may be distributed under the terms of the BSD license. |
6 | | * See README for more details. |
7 | | */ |
8 | | |
9 | | #include "utils/includes.h" |
10 | | |
11 | | #include "utils/common.h" |
12 | | #include "utils/eloop.h" |
13 | | #include "rsn_supp/wpa.h" |
14 | | #include "../fuzzer-common.h" |
15 | | |
16 | | |
17 | | struct wpa { |
18 | | const u8 *data; |
19 | | size_t data_len; |
20 | | size_t data_offset; |
21 | | int wpa1; |
22 | | |
23 | | u8 auth_addr[ETH_ALEN]; |
24 | | u8 supp_addr[ETH_ALEN]; |
25 | | u8 psk[PMK_LEN]; |
26 | | |
27 | | /* from authenticator */ |
28 | | u8 *auth_eapol; |
29 | | size_t auth_eapol_len; |
30 | | |
31 | | struct wpa_sm *supp; |
32 | | |
33 | | u8 supp_ie[80]; |
34 | | size_t supp_ie_len; |
35 | | }; |
36 | | |
37 | | |
38 | | const struct wpa_driver_ops *const wpa_drivers[] = { NULL }; |
39 | | |
40 | | |
41 | | static u8 * read_msg(struct wpa *wpa, size_t *ret_len) |
42 | 12.3k | { |
43 | 12.3k | u16 msg_len; |
44 | 12.3k | u8 *msg; |
45 | | |
46 | 12.3k | if (wpa->data_len - wpa->data_offset < 2) { |
47 | 1.15k | wpa_printf(MSG_ERROR, "TEST-ERROR: Could not read msg len"); |
48 | 1.15k | eloop_terminate(); |
49 | 1.15k | return NULL; |
50 | 1.15k | } |
51 | 11.2k | msg_len = WPA_GET_BE16(&wpa->data[wpa->data_offset]); |
52 | 11.2k | wpa->data_offset += 2; |
53 | | |
54 | 11.2k | msg = os_malloc(msg_len); |
55 | 11.2k | if (!msg) |
56 | 0 | return NULL; |
57 | 11.2k | if (msg_len > 0 && wpa->data_len - wpa->data_offset < msg_len) { |
58 | 29 | wpa_printf(MSG_ERROR, "TEST-ERROR: Truncated msg (msg_len=%u)", |
59 | 29 | msg_len); |
60 | 29 | os_free(msg); |
61 | 29 | eloop_terminate(); |
62 | 29 | return NULL; |
63 | 29 | } |
64 | 11.1k | os_memcpy(msg, &wpa->data[wpa->data_offset], msg_len); |
65 | 11.1k | wpa->data_offset += msg_len; |
66 | 11.1k | wpa_hexdump(MSG_DEBUG, "TEST: Read message from file", msg, msg_len); |
67 | | |
68 | 11.1k | *ret_len = msg_len; |
69 | 11.1k | return msg; |
70 | 11.2k | } |
71 | | |
72 | | |
73 | | static int supp_get_bssid(void *ctx, u8 *bssid) |
74 | 0 | { |
75 | 0 | struct wpa *wpa = ctx; |
76 | 0 | wpa_printf(MSG_DEBUG, "SUPP: %s", __func__); |
77 | 0 | os_memcpy(bssid, wpa->auth_addr, ETH_ALEN); |
78 | 0 | return 0; |
79 | 0 | } |
80 | | |
81 | | |
82 | | static void supp_set_state(void *ctx, enum wpa_states state) |
83 | 11.3k | { |
84 | 11.3k | wpa_printf(MSG_DEBUG, "SUPP: %s(state=%d)", __func__, state); |
85 | 11.3k | } |
86 | | |
87 | | |
88 | | static void supp_eapol_rx(void *eloop_data, void *user_ctx) |
89 | 11.1k | { |
90 | 11.1k | struct wpa *wpa = eloop_data; |
91 | | |
92 | 11.1k | wpa_printf(MSG_DEBUG, "SUPP: RX EAPOL frame"); |
93 | 11.1k | wpa_sm_rx_eapol(wpa->supp, wpa->auth_addr, wpa->auth_eapol, |
94 | 11.1k | wpa->auth_eapol_len, FRAME_ENCRYPTION_UNKNOWN); |
95 | 11.1k | } |
96 | | |
97 | | |
98 | | static int supp_read_msg(struct wpa *wpa) |
99 | 12.3k | { |
100 | 12.3k | os_free(wpa->auth_eapol); |
101 | 12.3k | wpa->auth_eapol = read_msg(wpa, &wpa->auth_eapol_len); |
102 | 12.3k | if (!wpa->auth_eapol) |
103 | 1.18k | return -1; |
104 | 11.1k | eloop_register_timeout(0, 0, supp_eapol_rx, wpa, NULL); |
105 | 11.1k | return 0; |
106 | 12.3k | } |
107 | | |
108 | | |
109 | | static int supp_ether_send(void *ctx, const u8 *dest, u16 proto, const u8 *buf, |
110 | | size_t len) |
111 | 10.3k | { |
112 | 10.3k | struct wpa *wpa = ctx; |
113 | | |
114 | 10.3k | wpa_printf(MSG_DEBUG, "SUPP: %s(dest=" MACSTR " proto=0x%04x " |
115 | 10.3k | "len=%lu)", |
116 | 10.3k | __func__, MAC2STR(dest), proto, (unsigned long) len); |
117 | | |
118 | 10.3k | return supp_read_msg(wpa); |
119 | 10.3k | } |
120 | | |
121 | | |
122 | | static u8 * supp_alloc_eapol(void *ctx, u8 type, const void *data, |
123 | | u16 data_len, size_t *msg_len, void **data_pos) |
124 | 10.3k | { |
125 | 10.3k | struct ieee802_1x_hdr *hdr; |
126 | | |
127 | 10.3k | wpa_printf(MSG_DEBUG, "SUPP: %s(type=%d data_len=%d)", |
128 | 10.3k | __func__, type, data_len); |
129 | | |
130 | 10.3k | *msg_len = sizeof(*hdr) + data_len; |
131 | 10.3k | hdr = os_malloc(*msg_len); |
132 | 10.3k | if (hdr == NULL) |
133 | 0 | return NULL; |
134 | | |
135 | 10.3k | hdr->version = 2; |
136 | 10.3k | hdr->type = type; |
137 | 10.3k | hdr->length = host_to_be16(data_len); |
138 | | |
139 | 10.3k | if (data) |
140 | 0 | os_memcpy(hdr + 1, data, data_len); |
141 | 10.3k | else |
142 | 10.3k | os_memset(hdr + 1, 0, data_len); |
143 | | |
144 | 10.3k | if (data_pos) |
145 | 10.3k | *data_pos = hdr + 1; |
146 | | |
147 | 10.3k | return (u8 *) hdr; |
148 | 10.3k | } |
149 | | |
150 | | |
151 | | static int supp_get_beacon_ie(void *ctx) |
152 | 270 | { |
153 | 270 | struct wpa *wpa = ctx; |
154 | 270 | const u8 *ie; |
155 | 270 | static const u8 wpaie[] = { |
156 | 270 | 0xdd, 0x16, 0x00, 0x50, 0xf2, 0x01, 0x01, 0x00, |
157 | 270 | 0x00, 0x50, 0xf2, 0x02, 0x01, 0x00, 0x00, 0x50, |
158 | 270 | 0xf2, 0x02, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x02 |
159 | 270 | }; |
160 | 270 | static const u8 rsne[] = { |
161 | 270 | 0x30, 0x14, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04, |
162 | 270 | 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04, 0x01, 0x00, |
163 | 270 | 0x00, 0x0f, 0xac, 0x02, 0xc0, 0x00 |
164 | 270 | }; |
165 | | |
166 | 270 | wpa_printf(MSG_DEBUG, "SUPP: %s", __func__); |
167 | | |
168 | 270 | ie = wpa->wpa1 ? wpaie : rsne; |
169 | 270 | if (ie[0] == WLAN_EID_RSN) |
170 | 270 | return wpa_sm_set_ap_rsn_ie(wpa->supp, ie, 2 + ie[1]); |
171 | 0 | return wpa_sm_set_ap_wpa_ie(wpa->supp, ie, 2 + ie[1]); |
172 | 270 | } |
173 | | |
174 | | |
175 | | static int supp_set_key(void *ctx, int link_id, enum wpa_alg alg, |
176 | | const u8 *addr, int key_idx, int set_tx, |
177 | | const u8 *seq, size_t seq_len, |
178 | | const u8 *key, size_t key_len, enum key_flag key_flag) |
179 | 535 | { |
180 | 535 | wpa_printf(MSG_DEBUG, "SUPP: %s(alg=%d addr=" MACSTR " key_idx=%d " |
181 | 535 | "set_tx=%d key_flag=0x%x link_id=%d)", |
182 | 535 | __func__, alg, MAC2STR(addr), key_idx, set_tx, key_flag, |
183 | 535 | link_id); |
184 | 535 | wpa_hexdump(MSG_DEBUG, "SUPP: set_key - seq", seq, seq_len); |
185 | 535 | wpa_hexdump(MSG_DEBUG, "SUPP: set_key - key", key, key_len); |
186 | 535 | return 0; |
187 | 535 | } |
188 | | |
189 | | |
190 | | static int supp_mlme_setprotection(void *ctx, const u8 *addr, |
191 | | int protection_type, int key_type) |
192 | 449 | { |
193 | 449 | wpa_printf(MSG_DEBUG, "SUPP: %s(addr=" MACSTR " protection_type=%d " |
194 | 449 | "key_type=%d)", |
195 | 449 | __func__, MAC2STR(addr), protection_type, key_type); |
196 | 449 | return 0; |
197 | 449 | } |
198 | | |
199 | | |
200 | | static void supp_cancel_auth_timeout(void *ctx) |
201 | 0 | { |
202 | 0 | wpa_printf(MSG_DEBUG, "SUPP: %s", __func__); |
203 | 0 | } |
204 | | |
205 | | |
206 | | static void * supp_get_network_ctx(void *ctx) |
207 | 9.79k | { |
208 | 9.79k | return (void *) 1; |
209 | 9.79k | } |
210 | | |
211 | | |
212 | | static void supp_deauthenticate(void *ctx, u16 reason_code) |
213 | 2.31k | { |
214 | 2.31k | wpa_printf(MSG_DEBUG, "SUPP: %s(%d)", __func__, reason_code); |
215 | 2.31k | } |
216 | | |
217 | | |
218 | | static enum wpa_states supp_get_state(void *ctx) |
219 | 0 | { |
220 | 0 | return WPA_COMPLETED; |
221 | 0 | } |
222 | | |
223 | | |
224 | | static int supp_init(struct wpa *wpa) |
225 | 2.02k | { |
226 | 2.02k | struct wpa_sm_ctx *ctx = os_zalloc(sizeof(*ctx)); |
227 | | |
228 | 2.02k | if (!ctx) |
229 | 0 | return -1; |
230 | | |
231 | 2.02k | ctx->ctx = wpa; |
232 | 2.02k | ctx->msg_ctx = wpa; |
233 | 2.02k | ctx->set_state = supp_set_state; |
234 | 2.02k | ctx->get_bssid = supp_get_bssid; |
235 | 2.02k | ctx->ether_send = supp_ether_send; |
236 | 2.02k | ctx->get_beacon_ie = supp_get_beacon_ie; |
237 | 2.02k | ctx->alloc_eapol = supp_alloc_eapol; |
238 | 2.02k | ctx->set_key = supp_set_key; |
239 | 2.02k | ctx->mlme_setprotection = supp_mlme_setprotection; |
240 | 2.02k | ctx->cancel_auth_timeout = supp_cancel_auth_timeout; |
241 | 2.02k | ctx->get_network_ctx = supp_get_network_ctx; |
242 | 2.02k | ctx->deauthenticate = supp_deauthenticate; |
243 | 2.02k | ctx->get_state = supp_get_state; |
244 | 2.02k | wpa->supp = wpa_sm_init(ctx); |
245 | 2.02k | if (!wpa->supp) { |
246 | 0 | wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_init() failed"); |
247 | 0 | return -1; |
248 | 0 | } |
249 | | |
250 | 2.02k | wpa_sm_set_own_addr(wpa->supp, wpa->supp_addr); |
251 | 2.02k | if (wpa->wpa1) { |
252 | 0 | wpa_sm_set_param(wpa->supp, WPA_PARAM_RSN_ENABLED, 0); |
253 | 0 | wpa_sm_set_param(wpa->supp, WPA_PARAM_PROTO, WPA_PROTO_WPA); |
254 | 0 | wpa_sm_set_param(wpa->supp, WPA_PARAM_PAIRWISE, |
255 | 0 | WPA_CIPHER_TKIP); |
256 | 0 | wpa_sm_set_param(wpa->supp, WPA_PARAM_GROUP, WPA_CIPHER_TKIP); |
257 | 0 | wpa_sm_set_param(wpa->supp, WPA_PARAM_KEY_MGMT, |
258 | 0 | WPA_KEY_MGMT_PSK); |
259 | 2.02k | } else { |
260 | 2.02k | wpa_sm_set_param(wpa->supp, WPA_PARAM_RSN_ENABLED, 1); |
261 | 2.02k | wpa_sm_set_param(wpa->supp, WPA_PARAM_PROTO, WPA_PROTO_RSN); |
262 | 2.02k | wpa_sm_set_param(wpa->supp, WPA_PARAM_PAIRWISE, |
263 | 2.02k | WPA_CIPHER_CCMP); |
264 | 2.02k | wpa_sm_set_param(wpa->supp, WPA_PARAM_GROUP, WPA_CIPHER_CCMP); |
265 | 2.02k | wpa_sm_set_param(wpa->supp, WPA_PARAM_KEY_MGMT, |
266 | 2.02k | WPA_KEY_MGMT_PSK); |
267 | 2.02k | wpa_sm_set_param(wpa->supp, WPA_PARAM_MFP, |
268 | 2.02k | MGMT_FRAME_PROTECTION_OPTIONAL); |
269 | 2.02k | } |
270 | 2.02k | wpa_sm_set_pmk(wpa->supp, wpa->psk, PMK_LEN, NULL, NULL); |
271 | | |
272 | 2.02k | wpa->supp_ie_len = sizeof(wpa->supp_ie); |
273 | 2.02k | if (wpa_sm_set_assoc_wpa_ie_default(wpa->supp, wpa->supp_ie, |
274 | 2.02k | &wpa->supp_ie_len) < 0) { |
275 | 0 | wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_set_assoc_wpa_ie_default()" |
276 | 0 | " failed"); |
277 | 0 | return -1; |
278 | 0 | } |
279 | | |
280 | 2.02k | wpa_sm_notify_assoc(wpa->supp, wpa->auth_addr); |
281 | 2.02k | supp_read_msg(wpa); |
282 | | |
283 | 2.02k | return 0; |
284 | 2.02k | } |
285 | | |
286 | | |
287 | | static void deinit(struct wpa *wpa) |
288 | 2.02k | { |
289 | 2.02k | wpa_sm_deinit(wpa->supp); |
290 | 2.02k | os_free(wpa->auth_eapol); |
291 | 2.02k | wpa->auth_eapol = NULL; |
292 | 2.02k | } |
293 | | |
294 | | |
295 | | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) |
296 | 2.02k | { |
297 | 2.02k | struct wpa wpa; |
298 | | |
299 | 2.02k | wpa_fuzzer_set_debug_level(); |
300 | | |
301 | 2.02k | if (os_program_init()) |
302 | 0 | return -1; |
303 | | |
304 | 2.02k | os_memset(&wpa, 0, sizeof(wpa)); |
305 | 2.02k | wpa.data = data; |
306 | 2.02k | wpa.data_len = size; |
307 | | |
308 | 2.02k | os_memset(wpa.auth_addr, 0x12, ETH_ALEN); |
309 | 2.02k | os_memset(wpa.supp_addr, 0x32, ETH_ALEN); |
310 | 2.02k | os_memset(wpa.psk, 0x44, PMK_LEN); |
311 | | |
312 | 2.02k | if (eloop_init()) { |
313 | 0 | wpa_printf(MSG_ERROR, "Failed to initialize event loop"); |
314 | 0 | goto fail; |
315 | 0 | } |
316 | | |
317 | 2.02k | if (supp_init(&wpa) < 0) |
318 | 0 | goto fail; |
319 | | |
320 | 2.02k | wpa_printf(MSG_DEBUG, "Starting eloop"); |
321 | 2.02k | eloop_run(); |
322 | 2.02k | wpa_printf(MSG_DEBUG, "eloop done"); |
323 | | |
324 | 2.02k | fail: |
325 | 2.02k | deinit(&wpa); |
326 | | |
327 | 2.02k | eloop_destroy(); |
328 | | |
329 | 2.02k | os_program_deinit(); |
330 | | |
331 | 2.02k | return 0; |
332 | 2.02k | } |