Coverage Report

Created: 2025-10-10 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hostap/tests/fuzzing/eapol-key-supp/eapol-key-supp.c
Line
Count
Source
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
11.2k
{
43
11.2k
  u16 msg_len;
44
11.2k
  u8 *msg;
45
46
11.2k
  if (wpa->data_len - wpa->data_offset < 2) {
47
1.14k
    wpa_printf(MSG_ERROR, "TEST-ERROR: Could not read msg len");
48
1.14k
    eloop_terminate();
49
1.14k
    return NULL;
50
1.14k
  }
51
10.1k
  msg_len = WPA_GET_BE16(&wpa->data[wpa->data_offset]);
52
10.1k
  wpa->data_offset += 2;
53
54
10.1k
  msg = os_malloc(msg_len);
55
10.1k
  if (!msg)
56
0
    return NULL;
57
10.1k
  if (msg_len > 0 && wpa->data_len - wpa->data_offset < msg_len) {
58
30
    wpa_printf(MSG_ERROR, "TEST-ERROR: Truncated msg (msg_len=%u)",
59
30
         msg_len);
60
30
    os_free(msg);
61
30
    eloop_terminate();
62
30
    return NULL;
63
30
  }
64
10.0k
  os_memcpy(msg, &wpa->data[wpa->data_offset], msg_len);
65
10.0k
  wpa->data_offset += msg_len;
66
10.0k
  wpa_hexdump(MSG_DEBUG, "TEST: Read message from file", msg, msg_len);
67
68
10.0k
  *ret_len = msg_len;
69
10.0k
  return msg;
70
10.1k
}
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
10.2k
{
84
10.2k
  wpa_printf(MSG_DEBUG, "SUPP: %s(state=%d)", __func__, state);
85
10.2k
}
86
87
88
static void supp_eapol_rx(void *eloop_data, void *user_ctx)
89
10.0k
{
90
10.0k
  struct wpa *wpa = eloop_data;
91
92
10.0k
  wpa_printf(MSG_DEBUG, "SUPP: RX EAPOL frame");
93
10.0k
  wpa_sm_rx_eapol(wpa->supp, wpa->auth_addr, wpa->auth_eapol,
94
10.0k
      wpa->auth_eapol_len, FRAME_ENCRYPTION_UNKNOWN);
95
10.0k
}
96
97
98
static int supp_read_msg(struct wpa *wpa)
99
11.2k
{
100
11.2k
  os_free(wpa->auth_eapol);
101
11.2k
  wpa->auth_eapol = read_msg(wpa, &wpa->auth_eapol_len);
102
11.2k
  if (!wpa->auth_eapol)
103
1.17k
    return -1;
104
10.0k
  eloop_register_timeout(0, 0, supp_eapol_rx, wpa, NULL);
105
10.0k
  return 0;
106
11.2k
}
107
108
109
static int supp_ether_send(void *ctx, const u8 *dest, u16 proto, const u8 *buf,
110
         size_t len)
111
9.24k
{
112
9.24k
  struct wpa *wpa = ctx;
113
114
9.24k
  wpa_printf(MSG_DEBUG, "SUPP: %s(dest=" MACSTR " proto=0x%04x "
115
9.24k
       "len=%lu)",
116
9.24k
       __func__, MAC2STR(dest), proto, (unsigned long) len);
117
118
9.24k
  return supp_read_msg(wpa);
119
9.24k
}
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
9.24k
{
125
9.24k
  struct ieee802_1x_hdr *hdr;
126
127
9.24k
  wpa_printf(MSG_DEBUG, "SUPP: %s(type=%d data_len=%d)",
128
9.24k
       __func__, type, data_len);
129
130
9.24k
  *msg_len = sizeof(*hdr) + data_len;
131
9.24k
  hdr = os_malloc(*msg_len);
132
9.24k
  if (hdr == NULL)
133
0
    return NULL;
134
135
9.24k
  hdr->version = 2;
136
9.24k
  hdr->type = type;
137
9.24k
  hdr->length = host_to_be16(data_len);
138
139
9.24k
  if (data)
140
0
    os_memcpy(hdr + 1, data, data_len);
141
9.24k
  else
142
9.24k
    os_memset(hdr + 1, 0, data_len);
143
144
9.24k
  if (data_pos)
145
9.24k
    *data_pos = hdr + 1;
146
147
9.24k
  return (u8 *) hdr;
148
9.24k
}
149
150
151
static int supp_get_beacon_ie(void *ctx)
152
283
{
153
283
  struct wpa *wpa = ctx;
154
283
  const u8 *ie;
155
283
  static const u8 wpaie[] = {
156
283
    0xdd, 0x16, 0x00, 0x50, 0xf2, 0x01, 0x01, 0x00,
157
283
    0x00, 0x50, 0xf2, 0x02, 0x01, 0x00, 0x00, 0x50,
158
283
    0xf2, 0x02, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x02
159
283
  };
160
283
  static const u8 rsne[] = {
161
283
    0x30, 0x14, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04,
162
283
    0x01, 0x00, 0x00, 0x0f, 0xac, 0x04, 0x01, 0x00,
163
283
    0x00, 0x0f, 0xac, 0x02, 0xc0, 0x00
164
283
  };
165
166
283
  wpa_printf(MSG_DEBUG, "SUPP: %s", __func__);
167
168
283
  ie = wpa->wpa1 ? wpaie : rsne;
169
283
  if (ie[0] == WLAN_EID_RSN)
170
283
    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
283
}
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
558
{
180
558
  wpa_printf(MSG_DEBUG, "SUPP: %s(alg=%d addr=" MACSTR " key_idx=%d "
181
558
       "set_tx=%d key_flag=0x%x link_id=%d)",
182
558
       __func__, alg, MAC2STR(addr), key_idx, set_tx, key_flag,
183
558
       link_id);
184
558
  wpa_hexdump(MSG_DEBUG, "SUPP: set_key - seq", seq, seq_len);
185
558
  wpa_hexdump(MSG_DEBUG, "SUPP: set_key - key", key, key_len);
186
558
  return 0;
187
558
}
188
189
190
static int supp_mlme_setprotection(void *ctx, const u8 *addr,
191
           int protection_type, int key_type)
192
455
{
193
455
  wpa_printf(MSG_DEBUG, "SUPP: %s(addr=" MACSTR " protection_type=%d "
194
455
       "key_type=%d)",
195
455
       __func__, MAC2STR(addr), protection_type, key_type);
196
455
  return 0;
197
455
}
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
8.68k
{
208
8.68k
  return (void *) 1;
209
8.68k
}
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.01k
{
226
2.01k
  struct wpa_sm_ctx *ctx = os_zalloc(sizeof(*ctx));
227
228
2.01k
  if (!ctx)
229
0
    return -1;
230
231
2.01k
  ctx->ctx = wpa;
232
2.01k
  ctx->msg_ctx = wpa;
233
2.01k
  ctx->set_state = supp_set_state;
234
2.01k
  ctx->get_bssid = supp_get_bssid;
235
2.01k
  ctx->ether_send = supp_ether_send;
236
2.01k
  ctx->get_beacon_ie = supp_get_beacon_ie;
237
2.01k
  ctx->alloc_eapol = supp_alloc_eapol;
238
2.01k
  ctx->set_key = supp_set_key;
239
2.01k
  ctx->mlme_setprotection = supp_mlme_setprotection;
240
2.01k
  ctx->cancel_auth_timeout = supp_cancel_auth_timeout;
241
2.01k
  ctx->get_network_ctx = supp_get_network_ctx;
242
2.01k
  ctx->deauthenticate = supp_deauthenticate;
243
2.01k
  ctx->get_state = supp_get_state;
244
2.01k
  wpa->supp = wpa_sm_init(ctx);
245
2.01k
  if (!wpa->supp) {
246
0
    wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_init() failed");
247
0
    return -1;
248
0
  }
249
250
2.01k
  wpa_sm_set_own_addr(wpa->supp, wpa->supp_addr);
251
2.01k
  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.01k
  } else {
260
2.01k
    wpa_sm_set_param(wpa->supp, WPA_PARAM_RSN_ENABLED, 1);
261
2.01k
    wpa_sm_set_param(wpa->supp, WPA_PARAM_PROTO, WPA_PROTO_RSN);
262
2.01k
    wpa_sm_set_param(wpa->supp, WPA_PARAM_PAIRWISE,
263
2.01k
         WPA_CIPHER_CCMP);
264
2.01k
    wpa_sm_set_param(wpa->supp, WPA_PARAM_GROUP, WPA_CIPHER_CCMP);
265
2.01k
    wpa_sm_set_param(wpa->supp, WPA_PARAM_KEY_MGMT,
266
2.01k
         WPA_KEY_MGMT_PSK);
267
2.01k
    wpa_sm_set_param(wpa->supp, WPA_PARAM_MFP,
268
2.01k
         MGMT_FRAME_PROTECTION_OPTIONAL);
269
2.01k
  }
270
2.01k
  wpa_sm_set_pmk(wpa->supp, wpa->psk, PMK_LEN, NULL, NULL);
271
272
2.01k
  wpa->supp_ie_len = sizeof(wpa->supp_ie);
273
2.01k
  if (wpa_sm_set_assoc_wpa_ie_default(wpa->supp, wpa->supp_ie,
274
2.01k
              &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.01k
  wpa_sm_notify_assoc(wpa->supp, wpa->auth_addr);
281
2.01k
  supp_read_msg(wpa);
282
283
2.01k
  return 0;
284
2.01k
}
285
286
287
static void deinit(struct wpa *wpa)
288
2.01k
{
289
2.01k
  wpa_sm_deinit(wpa->supp);
290
2.01k
  os_free(wpa->auth_eapol);
291
2.01k
  wpa->auth_eapol = NULL;
292
2.01k
}
293
294
295
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
296
2.01k
{
297
2.01k
  struct wpa wpa;
298
299
2.01k
  wpa_fuzzer_set_debug_level();
300
301
2.01k
  if (os_program_init())
302
0
    return -1;
303
304
2.01k
  os_memset(&wpa, 0, sizeof(wpa));
305
2.01k
  wpa.data = data;
306
2.01k
  wpa.data_len = size;
307
308
2.01k
  os_memset(wpa.auth_addr, 0x12, ETH_ALEN);
309
2.01k
  os_memset(wpa.supp_addr, 0x32, ETH_ALEN);
310
2.01k
  os_memset(wpa.psk, 0x44, PMK_LEN);
311
312
2.01k
  if (eloop_init()) {
313
0
    wpa_printf(MSG_ERROR, "Failed to initialize event loop");
314
0
    goto fail;
315
0
  }
316
317
2.01k
  if (supp_init(&wpa) < 0)
318
0
    goto fail;
319
320
2.01k
  wpa_printf(MSG_DEBUG, "Starting eloop");
321
2.01k
  eloop_run();
322
2.01k
  wpa_printf(MSG_DEBUG, "eloop done");
323
324
2.01k
fail:
325
2.01k
  deinit(&wpa);
326
327
2.01k
  eloop_destroy();
328
329
2.01k
  os_program_deinit();
330
331
2.01k
  return 0;
332
2.01k
}