Coverage Report

Created: 2025-07-11 06:14

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